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