OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <numeric> | 5 #include <numeric> |
6 #include <utility> | 6 #include <utility> |
7 | 7 |
8 #include "base/base64.h" | 8 #include "base/base64.h" |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 if (!done.is_null()) | 156 if (!done.is_null()) |
157 done.Run(); | 157 done.Run(); |
158 } | 158 } |
159 | 159 |
160 protocol::FrameConsumer::PixelFormat GetPixelFormat() override { | 160 protocol::FrameConsumer::PixelFormat GetPixelFormat() override { |
161 return FORMAT_BGRA; | 161 return FORMAT_BGRA; |
162 } | 162 } |
163 | 163 |
164 // FrameStatsConsumer interface. | 164 // FrameStatsConsumer interface. |
165 void OnVideoFrameStats(const protocol::FrameStats& frame_stats) override { | 165 void OnVideoFrameStats(const protocol::FrameStats& frame_stats) override { |
166 // Ignore store stats for empty frames. | |
167 if (!frame_stats.host_stats.frame_size) | |
168 return; | |
169 | |
170 frame_stats_.push_back(frame_stats); | 166 frame_stats_.push_back(frame_stats); |
171 | 167 |
172 if (waiting_frame_stats_loop_ && | 168 if (waiting_frame_stats_loop_ && |
173 frame_stats_.size() >= num_expected_frame_stats_) { | 169 frame_stats_.size() >= num_expected_frame_stats_) { |
174 waiting_frame_stats_loop_->Quit(); | 170 waiting_frame_stats_loop_->Quit(); |
175 } | 171 } |
176 } | 172 } |
177 | 173 |
178 // HostStatusObserver interface. | 174 // HostStatusObserver interface. |
179 void OnClientAuthenticated(const std::string& jid) override { | |
180 if (event_timestamp_source_) { | |
181 auto& session = host_->client_sessions_for_tests().front(); | |
182 session->SetEventTimestampsSourceForTests( | |
183 std::move(event_timestamp_source_)); | |
184 } | |
185 } | |
186 | |
187 void OnClientConnected(const std::string& jid) override { | 175 void OnClientConnected(const std::string& jid) override { |
188 message_loop_.task_runner()->PostTask( | 176 message_loop_.task_runner()->PostTask( |
189 FROM_HERE, base::Bind(&ProtocolPerfTest::OnHostConnectedMainThread, | 177 FROM_HERE, base::Bind(&ProtocolPerfTest::OnHostConnectedMainThread, |
190 base::Unretained(this))); | 178 base::Unretained(this))); |
191 } | 179 } |
192 | 180 |
193 protected: | 181 protected: |
194 void WaitConnected() { | 182 void WaitConnected() { |
195 client_connected_ = false; | 183 client_connected_ = false; |
196 host_connected_ = false; | 184 host_connected_ = false; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 base::MessageLoopForIO message_loop_; | 353 base::MessageLoopForIO message_loop_; |
366 | 354 |
367 scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; | 355 scoped_refptr<FakeNetworkDispatcher> fake_network_dispatcher_; |
368 | 356 |
369 base::Thread host_thread_; | 357 base::Thread host_thread_; |
370 base::Thread capture_thread_; | 358 base::Thread capture_thread_; |
371 base::Thread encode_thread_; | 359 base::Thread encode_thread_; |
372 base::Thread decode_thread_; | 360 base::Thread decode_thread_; |
373 std::unique_ptr<FakeDesktopEnvironmentFactory> desktop_environment_factory_; | 361 std::unique_ptr<FakeDesktopEnvironmentFactory> desktop_environment_factory_; |
374 | 362 |
375 scoped_refptr<protocol::InputEventTimestampsSource> event_timestamp_source_; | |
376 | |
377 FakeCursorShapeStub cursor_shape_stub_; | 363 FakeCursorShapeStub cursor_shape_stub_; |
378 | 364 |
379 std::unique_ptr<protocol::CandidateSessionConfig> protocol_config_; | 365 std::unique_ptr<protocol::CandidateSessionConfig> protocol_config_; |
380 | 366 |
381 std::unique_ptr<FakeSignalStrategy> host_signaling_; | 367 std::unique_ptr<FakeSignalStrategy> host_signaling_; |
382 std::unique_ptr<FakeSignalStrategy> client_signaling_; | 368 std::unique_ptr<FakeSignalStrategy> client_signaling_; |
383 | 369 |
384 std::unique_ptr<ChromotingHost> host_; | 370 std::unique_ptr<ChromotingHost> host_; |
385 std::unique_ptr<ClientContext> client_context_; | 371 std::unique_ptr<ClientContext> client_context_; |
386 std::unique_ptr<SoftwareVideoRenderer> video_renderer_; | 372 std::unique_ptr<SoftwareVideoRenderer> video_renderer_; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 NetworkPerformanceParams(100000, 30000, 130, 5, 0.00), | 429 NetworkPerformanceParams(100000, 30000, 130, 5, 0.00), |
444 NetworkPerformanceParams(100000, 200000, 130, 5, 0.00))); | 430 NetworkPerformanceParams(100000, 200000, 130, 5, 0.00))); |
445 | 431 |
446 // TotalLatency[Ice|Webrtc] tests measure video latency in the case when the | 432 // TotalLatency[Ice|Webrtc] tests measure video latency in the case when the |
447 // whole screen is updated occasionally. It's intended to simulate the case when | 433 // whole screen is updated occasionally. It's intended to simulate the case when |
448 // user actions (e.g. Alt-Tab, click on the task bar) cause whole screen to be | 434 // user actions (e.g. Alt-Tab, click on the task bar) cause whole screen to be |
449 // updated. | 435 // updated. |
450 void ProtocolPerfTest::MeasureTotalLatency(bool use_webrtc) { | 436 void ProtocolPerfTest::MeasureTotalLatency(bool use_webrtc) { |
451 scoped_refptr<test::CyclicFrameGenerator> frame_generator = | 437 scoped_refptr<test::CyclicFrameGenerator> frame_generator = |
452 test::CyclicFrameGenerator::Create(); | 438 test::CyclicFrameGenerator::Create(); |
| 439 frame_generator->set_draw_barcode(true); |
| 440 |
453 desktop_environment_factory_->set_frame_generator( | 441 desktop_environment_factory_->set_frame_generator( |
454 base::Bind(&test::CyclicFrameGenerator::GenerateFrame, frame_generator)); | 442 base::Bind(&test::CyclicFrameGenerator::GenerateFrame, frame_generator)); |
455 event_timestamp_source_ = frame_generator; | |
456 | 443 |
457 StartHostAndClient(use_webrtc); | 444 StartHostAndClient(use_webrtc); |
458 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 445 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
459 | 446 |
460 int total_frames = 0; | 447 int skipped_frames = 0; |
461 | 448 while (skipped_frames < 10) { |
462 const base::TimeDelta kWarmUpTime = base::TimeDelta::FromSeconds(2); | 449 std::unique_ptr<webrtc::DesktopFrame> frame = ReceiveFrame(); |
463 const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(5); | 450 test::CyclicFrameGenerator::ChangeInfoList changes = |
464 | 451 frame_generator->GetChangeList(frame.get()); |
465 base::TimeTicks start_time = base::TimeTicks::Now(); | 452 skipped_frames += changes.size(); |
466 while ((base::TimeTicks::Now() - start_time) < (kWarmUpTime + kTestTime)) { | |
467 ReceiveFrame(); | |
468 ++total_frames; | |
469 } | 453 } |
470 | 454 |
471 WaitFrameStats(total_frames); | 455 base::TimeDelta total_latency_big_frames; |
| 456 int big_frame_count = 0; |
| 457 base::TimeDelta total_latency_small_frames; |
| 458 int small_frame_count = 0; |
472 | 459 |
473 int warm_up_frames = 0; | 460 while (big_frame_count + small_frame_count < 30) { |
474 | 461 std::unique_ptr<webrtc::DesktopFrame> frame = ReceiveFrame(); |
475 int big_update_count = 0; | 462 base::TimeTicks frame_received_time = base::TimeTicks::Now(); |
476 base::TimeDelta total_latency_big_updates; | |
477 int small_update_count = 0; | |
478 base::TimeDelta total_latency_small_updates; | |
479 for (int i = 0; i < total_frames; ++i) { | |
480 const protocol::FrameStats& stats = frame_stats_[i]; | |
481 | |
482 // CyclicFrameGenerator::TakeLastEventTimestamps() always returns non-null | |
483 // timestamps. | |
484 CHECK(!stats.host_stats.latest_event_timestamp.is_null()); | |
485 | |
486 test::CyclicFrameGenerator::ChangeInfoList changes = | 463 test::CyclicFrameGenerator::ChangeInfoList changes = |
487 frame_generator->GetChangeList(stats.host_stats.latest_event_timestamp); | 464 frame_generator->GetChangeList(frame.get()); |
488 | |
489 // Allow 2 seconds for the connection to warm-up, e.g. to get bandwidth | |
490 // estimate, etc. These frames are ignored when calculating stats below. | |
491 if (stats.client_stats.time_rendered < (start_time + kWarmUpTime)) { | |
492 ++warm_up_frames; | |
493 continue; | |
494 } | |
495 | |
496 for (auto& change_info : changes) { | 465 for (auto& change_info : changes) { |
497 base::TimeDelta latency = | 466 base::TimeDelta latency = frame_received_time - change_info.timestamp; |
498 stats.client_stats.time_rendered - change_info.timestamp; | |
499 switch (change_info.type) { | 467 switch (change_info.type) { |
500 case test::CyclicFrameGenerator::ChangeType::NO_CHANGES: | 468 case test::CyclicFrameGenerator::ChangeType::NO_CHANGES: |
501 NOTREACHED(); | 469 NOTREACHED(); |
502 break; | 470 break; |
503 case test::CyclicFrameGenerator::ChangeType::FULL: | 471 case test::CyclicFrameGenerator::ChangeType::FULL: |
504 total_latency_big_updates += latency; | 472 total_latency_big_frames += latency; |
505 ++big_update_count; | 473 ++big_frame_count; |
506 break; | 474 break; |
507 case test::CyclicFrameGenerator::ChangeType::CURSOR: | 475 case test::CyclicFrameGenerator::ChangeType::CURSOR: |
508 total_latency_small_updates += latency; | 476 total_latency_small_frames += latency; |
509 ++small_update_count; | 477 ++small_frame_count; |
510 break; | 478 break; |
511 } | 479 } |
512 } | 480 } |
513 } | 481 } |
514 | 482 |
515 CHECK(big_update_count); | 483 CHECK(big_frame_count); |
516 VLOG(0) << "Average latency for big updates: " | 484 VLOG(0) << "Average latency for big frames: " |
517 << (total_latency_big_updates / big_update_count).InMillisecondsF(); | 485 << (total_latency_big_frames / big_frame_count).InMillisecondsF(); |
518 | 486 |
519 if (small_update_count) { | 487 if (small_frame_count) { |
520 VLOG(0) | 488 VLOG(0) |
521 << "Average latency for small updates: " | 489 << "Average latency for small frames: " |
522 << (total_latency_small_updates / small_update_count).InMillisecondsF(); | 490 << (total_latency_small_frames / small_frame_count).InMillisecondsF(); |
523 } | 491 } |
524 } | 492 } |
525 | 493 |
526 TEST_P(ProtocolPerfTest, TotalLatencyIce) { | 494 TEST_P(ProtocolPerfTest, TotalLatencyIce) { |
527 MeasureTotalLatency(false); | 495 MeasureTotalLatency(false); |
528 } | 496 } |
529 | 497 |
530 TEST_P(ProtocolPerfTest, TotalLatencyWebrtc) { | 498 TEST_P(ProtocolPerfTest, TotalLatencyWebrtc) { |
531 MeasureTotalLatency(true); | 499 MeasureTotalLatency(true); |
532 } | 500 } |
533 | 501 |
534 // ScrollPerformance[Ice|Webrtc] tests simulate whole screen being scrolled | 502 // ScrollPerformance[Ice|Webrtc] tests simulate whole screen being scrolled |
535 // continuously. They measure FPS and video latency. | 503 // continuously. They measure FPS and video latency. |
536 void ProtocolPerfTest::MeasureScrollPerformance(bool use_webrtc) { | 504 void ProtocolPerfTest::MeasureScrollPerformance(bool use_webrtc) { |
537 scoped_refptr<test::ScrollFrameGenerator> frame_generator = | 505 scoped_refptr<test::ScrollFrameGenerator> frame_generator = |
538 new test::ScrollFrameGenerator(); | 506 new test::ScrollFrameGenerator(); |
| 507 |
539 desktop_environment_factory_->set_frame_generator( | 508 desktop_environment_factory_->set_frame_generator( |
540 base::Bind(&test::ScrollFrameGenerator::GenerateFrame, frame_generator)); | 509 base::Bind(&test::ScrollFrameGenerator::GenerateFrame, frame_generator)); |
541 event_timestamp_source_ = frame_generator; | |
542 | 510 |
543 StartHostAndClient(use_webrtc); | 511 StartHostAndClient(use_webrtc); |
544 ASSERT_NO_FATAL_FAILURE(WaitConnected()); | 512 ASSERT_NO_FATAL_FAILURE(WaitConnected()); |
545 | 513 |
| 514 int warm_up_frames = 0; |
| 515 |
| 516 base::TimeTicks start_time = base::TimeTicks::Now(); |
546 const base::TimeDelta kWarmUpTime = base::TimeDelta::FromSeconds(2); | 517 const base::TimeDelta kWarmUpTime = base::TimeDelta::FromSeconds(2); |
| 518 while ((base::TimeTicks::Now() - start_time) < kWarmUpTime) { |
| 519 ReceiveFrame(); |
| 520 ++warm_up_frames; |
| 521 } |
| 522 |
| 523 client_socket_factory_->ResetStats(); |
| 524 |
| 525 // Run the test for 2 seconds. |
547 const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(2); | 526 const base::TimeDelta kTestTime = base::TimeDelta::FromSeconds(2); |
548 | 527 |
549 int num_frames = 0; | 528 int num_frames = 0; |
550 int warm_up_frames = 0; | 529 base::TimeDelta latency_sum; |
551 base::TimeTicks start_time = base::TimeTicks::Now(); | 530 start_time = base::TimeTicks::Now(); |
552 while ((base::TimeTicks::Now() - start_time) < (kTestTime + kWarmUpTime)) { | 531 while ((base::TimeTicks::Now() - start_time) < kTestTime) { |
553 ReceiveFrame(); | 532 std::unique_ptr<webrtc::DesktopFrame> frame = ReceiveFrame(); |
554 ++num_frames; | 533 ++num_frames; |
555 | 534 latency_sum += frame_generator->GetFrameLatency(*frame); |
556 // Allow 2 seconds for the connection to warm-up, e.g. to get bandwidth | |
557 // estimate, etc. These frames are ignored when calculating stats below. | |
558 if ((base::TimeTicks::Now() - start_time) < kWarmUpTime) { | |
559 ++warm_up_frames; | |
560 client_socket_factory_->ResetStats(); | |
561 } | |
562 } | 535 } |
563 | 536 |
564 base::TimeDelta total_time = (base::TimeTicks::Now() - start_time); | 537 base::TimeDelta total_time = (base::TimeTicks::Now() - start_time); |
565 | 538 |
566 WaitFrameStats(warm_up_frames + num_frames); | 539 WaitFrameStats(warm_up_frames + num_frames); |
567 | 540 |
568 int total_size = | 541 int total_size = |
569 std::accumulate(frame_stats_.begin() + warm_up_frames, | 542 std::accumulate(frame_stats_.begin() + warm_up_frames, |
570 frame_stats_.begin() + warm_up_frames + num_frames, 0, | 543 frame_stats_.begin() + warm_up_frames + num_frames, 0, |
571 [](int sum, const protocol::FrameStats& stats) { | 544 [](int sum, const protocol::FrameStats& stats) { |
572 return sum + stats.host_stats.frame_size; | 545 return sum + stats.host_stats.frame_size; |
573 }); | 546 }); |
574 | 547 |
575 base::TimeDelta latency_sum = std::accumulate( | |
576 frame_stats_.begin() + warm_up_frames, | |
577 frame_stats_.begin() + warm_up_frames + num_frames, base::TimeDelta(), | |
578 [](base::TimeDelta sum, const protocol::FrameStats& stats) { | |
579 return sum + (stats.client_stats.time_rendered - | |
580 stats.host_stats.latest_event_timestamp); | |
581 }); | |
582 | |
583 VLOG(0) << "FPS: " << num_frames / total_time.InSecondsF(); | 548 VLOG(0) << "FPS: " << num_frames / total_time.InSecondsF(); |
584 VLOG(0) << "Average latency: " << latency_sum.InMillisecondsF() / num_frames | 549 VLOG(0) << "Average latency: " << latency_sum.InMillisecondsF() / num_frames |
585 << " ms"; | 550 << " ms"; |
586 VLOG(0) << "Total size: " << total_size << " bytes"; | 551 VLOG(0) << "Total size: " << total_size << " bytes"; |
587 VLOG(0) << "Bandwidth utilization: " | 552 VLOG(0) << "Bandwidth utilization: " |
588 << 100 * total_size / (total_time.InSecondsF() * GetParam().bandwidth) | 553 << 100 * total_size / (total_time.InSecondsF() * GetParam().bandwidth) |
589 << "%"; | 554 << "%"; |
590 VLOG(0) << "Network buffer delay (bufferbloat), average: " | 555 VLOG(0) << "Network buffer delay (bufferbloat), average: " |
591 << client_socket_factory_->average_buffer_delay().InMilliseconds() | 556 << client_socket_factory_->average_buffer_delay().InMilliseconds() |
592 << " ms, max:" | 557 << " ms, max:" |
593 << client_socket_factory_->max_buffer_delay().InMilliseconds() | 558 << client_socket_factory_->max_buffer_delay().InMilliseconds() |
594 << " ms"; | 559 << " ms"; |
595 VLOG(0) << "Packet drop rate: " << client_socket_factory_->drop_rate(); | 560 VLOG(0) << "Packet drop rate: " << client_socket_factory_->drop_rate(); |
596 } | 561 } |
597 | 562 |
598 TEST_P(ProtocolPerfTest, ScrollPerformanceIce) { | 563 TEST_P(ProtocolPerfTest, ScrollPerformanceIce) { |
599 MeasureScrollPerformance(false); | 564 MeasureScrollPerformance(false); |
600 } | 565 } |
601 | 566 |
602 TEST_P(ProtocolPerfTest, ScrollPerformanceWebrtc) { | 567 TEST_P(ProtocolPerfTest, ScrollPerformanceWebrtc) { |
603 MeasureScrollPerformance(true); | 568 MeasureScrollPerformance(true); |
604 } | 569 } |
605 | 570 |
606 } // namespace remoting | 571 } // namespace remoting |
OLD | NEW |