Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(409)

Side by Side Diff: chrome/test/perf/rendering/latency_tests.cc

Issue 10378112: Make latency tests measure until the end of swap buffers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | content/browser/renderer_host/render_widget_host_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/command_line.h" 5 #include "base/command_line.h"
6 #include "base/file_util.h" 6 #include "base/file_util.h"
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/path_service.h" 8 #include "base/path_service.h"
9 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
10 #include "base/stringprintf.h" 10 #include "base/stringprintf.h"
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 const int kMinimumFramesForAnalysis = 5; 100 const int kMinimumFramesForAnalysis = 5;
101 101
102 class LatencyTest 102 class LatencyTest
103 : public BrowserPerfTest, 103 : public BrowserPerfTest,
104 public ::testing::WithParamInterface<int> { 104 public ::testing::WithParamInterface<int> {
105 public: 105 public:
106 LatencyTest() : 106 LatencyTest() :
107 query_instant_(Query::EventPhase() == 107 query_instant_(Query::EventPhase() ==
108 Query::Phase(TRACE_EVENT_PHASE_INSTANT)), 108 Query::Phase(TRACE_EVENT_PHASE_INSTANT)),
109 // These queries are initialized in RunTest. 109 // These queries are initialized in RunTest.
110 query_swaps_(Query::Bool(false)), 110 query_begin_swaps_(Query::Bool(false)),
111 query_end_swaps_(Query::Bool(false)),
111 query_inputs_(Query::Bool(false)), 112 query_inputs_(Query::Bool(false)),
112 query_blits_(Query::Bool(false)), 113 query_blits_(Query::Bool(false)),
113 query_clears_(Query::Bool(false)), 114 query_clears_(Query::Bool(false)),
114 mouse_x_(0), 115 mouse_x_(0),
115 tab_width_(0), 116 tab_width_(0),
116 mode_(kWebGL), 117 mode_(kWebGL),
117 delay_time_us_(0), 118 delay_time_us_(0),
118 num_frames_(0), 119 num_frames_(0),
119 verbose_(false), 120 verbose_(false),
120 test_flags_(0) {} 121 test_flags_(0) {}
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 void SendInput(); 159 void SendInput();
159 160
160 void PrintEvents(const TraceEventVector& events); 161 void PrintEvents(const TraceEventVector& events);
161 162
162 // Path to html file. 163 // Path to html file.
163 FilePath test_path_; 164 FilePath test_path_;
164 165
165 // Query INSTANT events. 166 // Query INSTANT events.
166 Query query_instant_; 167 Query query_instant_;
167 168
168 // Query "swaps" which is SwapBuffers for GL and UpdateRect for software. 169 // Query begin of "swaps" which is SwapBuffers for GL and UpdateRect for
169 Query query_swaps_; 170 // software.
171 Query query_begin_swaps_;
172
173 // Query end of "swaps" which is SwapBuffers for GL and UpdateRect for
174 // software.
175 Query query_end_swaps_;
170 176
171 // Query mouse input entry events in browser process (ForwardMouseEvent). 177 // Query mouse input entry events in browser process (ForwardMouseEvent).
172 Query query_inputs_; 178 Query query_inputs_;
173 179
174 // Query GL blits for the WebGL canvas -- represents the compositor consuming 180 // Query GL blits for the WebGL canvas -- represents the compositor consuming
175 // the WebGL contents for display. 181 // the WebGL contents for display.
176 Query query_blits_; 182 Query query_blits_;
177 183
178 // Query glClear calls with mouse coordinate as clear color. 184 // Query glClear calls with mouse coordinate as clear color.
179 Query query_clears_; 185 Query query_clears_;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 return behaviors; 238 return behaviors;
233 } 239 }
234 240
235 void LatencyTest::RunTest(LatencyTestMode mode, 241 void LatencyTest::RunTest(LatencyTestMode mode,
236 const std::vector<int>& behaviors) { 242 const std::vector<int>& behaviors) {
237 mode_ = mode; 243 mode_ = mode;
238 verbose_ = (logging::GetVlogLevel("latency_tests") > 0); 244 verbose_ = (logging::GetVlogLevel("latency_tests") > 0);
239 245
240 // Construct queries for searching trace events via TraceAnalyzer. 246 // Construct queries for searching trace events via TraceAnalyzer.
241 if (mode_ == kWebGL) { 247 if (mode_ == kWebGL) {
242 query_swaps_ = query_instant_ && 248 query_begin_swaps_ = query_instant_ &&
243 Query::EventName() == Query::String("SwapBuffers") && 249 Query::EventName() == Query::String("SwapBuffers") &&
244 Query::EventArg("width") != Query::Int(kWebGLCanvasWidth); 250 Query::EventArg("width") != Query::Int(kWebGLCanvasWidth);
251 query_end_swaps_ = query_instant_ &&
252 Query::EventName() == Query::String("CompositorSwapBuffersComplete");
245 } else if (mode_ == kSoftware) { 253 } else if (mode_ == kSoftware) {
246 // Software updates need to have x=0 and y=0 to contain the input color. 254 // Software updates need to have x=0 and y=0 to contain the input color.
247 query_swaps_ = query_instant_ && 255 query_begin_swaps_ = query_instant_ &&
248 Query::EventName() == Query::String("UpdateRect") && 256 Query::EventName() == Query::String("UpdateRect") &&
249 Query::EventArg("x+y") == Query::Int(0); 257 Query::EventArg("x+y") == Query::Int(0);
258 query_end_swaps_ = query_instant_ &&
259 Query::EventName() == Query::String("UpdateRectComplete") &&
260 Query::EventArg("x+y") == Query::Int(0);
250 } 261 }
251 query_inputs_ = query_instant_ && 262 query_inputs_ = query_instant_ &&
252 Query::EventName() == Query::String("MouseEventBegin"); 263 Query::EventName() == Query::String("MouseEventBegin");
253 query_blits_ = query_instant_ && 264 query_blits_ = query_instant_ &&
254 Query::EventName() == Query::String("DoBlit") && 265 Query::EventName() == Query::String("DoBlit") &&
255 Query::EventArg("width") == Query::Int(kWebGLCanvasWidth); 266 Query::EventArg("width") == Query::Int(kWebGLCanvasWidth);
256 query_clears_ = query_instant_ && 267 query_clears_ = query_instant_ &&
257 Query::EventName() == Query::String("DoClear") && 268 Query::EventName() == Query::String("DoClear") &&
258 Query::EventArg("green") == Query::Int(kClearColorGreen); 269 Query::EventArg("green") == Query::Int(kClearColorGreen);
259 Query query_width_swaps = query_swaps_; 270 Query query_width_swaps = query_begin_swaps_;
260 if (mode_ == kSoftware) { 271 if (mode_ == kSoftware) {
261 query_width_swaps = query_instant_ && 272 query_width_swaps = query_instant_ &&
262 Query::EventName() == Query::String("UpdateRectWidth") && 273 Query::EventName() == Query::String("UpdateRectWidth") &&
263 Query::EventArg("width") > Query::Int(kWebGLCanvasWidth); 274 Query::EventArg("width") > Query::Int(kWebGLCanvasWidth);
264 } 275 }
265 276
266 // Set path to test html. 277 // Set path to test html.
267 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path_)); 278 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_path_));
268 test_path_ = test_path_.Append(FILE_PATH_LITERAL("perf")); 279 test_path_ = test_path_.Append(FILE_PATH_LITERAL("perf"));
269 test_path_ = test_path_.Append(FILE_PATH_LITERAL("latency_suite.html")); 280 test_path_ = test_path_.Append(FILE_PATH_LITERAL("latency_suite.html"));
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 analyzer_->MergeAssociatedEventArgs(); 394 analyzer_->MergeAssociatedEventArgs();
384 } 395 }
385 396
386 double LatencyTest::CalculateLatency() { 397 double LatencyTest::CalculateLatency() {
387 TraceEventVector events; 398 TraceEventVector events;
388 if (mode_ == kWebGL) { 399 if (mode_ == kWebGL) {
389 // Search for three types of events in WebGL mode: 400 // Search for three types of events in WebGL mode:
390 // - onscreen swaps. 401 // - onscreen swaps.
391 // - DoClear calls that contain the mouse x coordinate. 402 // - DoClear calls that contain the mouse x coordinate.
392 // - mouse events. 403 // - mouse events.
393 analyzer_->FindEvents(query_swaps_ || query_inputs_ || 404 analyzer_->FindEvents(query_begin_swaps_ || query_end_swaps_ ||
394 query_blits_ || query_clears_, &events); 405 query_inputs_ || query_blits_ || query_clears_,
406 &events);
395 } else if (mode_ == kSoftware) { 407 } else if (mode_ == kSoftware) {
396 analyzer_->FindEvents(query_swaps_ || query_inputs_, &events); 408 analyzer_->FindEvents(query_begin_swaps_ || query_end_swaps_ ||
409 query_inputs_, &events);
397 } else { 410 } else {
398 NOTREACHED() << "invalid mode"; 411 NOTREACHED() << "invalid mode";
399 } 412 }
400 413
401 if (verbose_) 414 if (verbose_)
402 PrintEvents(events); 415 PrintEvents(events);
403 416
404 int swap_count = 0; 417 int swap_count = 0;
405 size_t previous_blit_pos = 0; 418 size_t previous_blit_pos = 0;
406 swap_count = 0; 419 swap_count = 0;
407 std::vector<int> latencies; 420 std::vector<int> latencies;
408 printf("Measured latency (in number of frames) for each frame:\n"); 421 printf("Measured latency (in number of frames) for each frame:\n");
409 for (size_t i = 0; i < events.size(); ++i) { 422 for (size_t i = 0; i < events.size(); ++i) {
410 if (query_swaps_.Evaluate(*events[i])) { 423 if (query_end_swaps_.Evaluate(*events[i])) {
424 size_t end_swap_pos = i;
425
411 // Compositor context swap buffers. 426 // Compositor context swap buffers.
412 ++swap_count; 427 ++swap_count;
413 // Don't analyze first few swaps, because they are filling the rendering 428 // Don't analyze first few swaps, because they are filling the rendering
414 // pipeline and may be unstable. 429 // pipeline and may be unstable.
415 if (swap_count > kIgnoreBeginFrames) { 430 if (swap_count > kIgnoreBeginFrames) {
431 // First, find the beginning of this swap.
432 size_t begin_swap_pos = 0;
433 EXPECT_TRUE(FindLastOf(events, query_begin_swaps_, end_swap_pos,
434 &begin_swap_pos));
435
416 int mouse_x = 0; 436 int mouse_x = 0;
417 if (mode_ == kWebGL) { 437 if (mode_ == kWebGL) {
418 // Trace backwards through the events to find the input event that 438 // Trace backwards through the events to find the input event that
419 // matches the glClear that was presented by this SwapBuffers. 439 // matches the glClear that was presented by this SwapBuffers.
420 440
421 // Step 1: Find the last blit (which will be the WebGL blit). 441 // Step 1: Find the last blit (which will be the WebGL blit).
422 size_t blit_pos = 0; 442 size_t blit_pos = 0;
423 EXPECT_TRUE(FindLastOf(events, query_blits_, i, &blit_pos)); 443 EXPECT_TRUE(FindLastOf(events, query_blits_, begin_swap_pos,
444 &blit_pos));
424 // Skip this SwapBuffers if the blit has already been consumed by a 445 // Skip this SwapBuffers if the blit has already been consumed by a
425 // previous SwapBuffers. This means the current frame did not receive 446 // previous SwapBuffers. This means the current frame did not receive
426 // an update from WebGL. 447 // an update from WebGL.
427 EXPECT_GT(blit_pos, previous_blit_pos); 448 EXPECT_GT(blit_pos, previous_blit_pos);
428 if (blit_pos == previous_blit_pos) { 449 if (blit_pos == previous_blit_pos) {
429 if (verbose_) 450 if (verbose_)
430 printf(" %03d: ERROR\n", swap_count); 451 printf(" %03d: ERROR\n", swap_count);
431 else 452 else
432 printf(" ERROR"); 453 printf(" ERROR");
433 continue; 454 continue;
434 } 455 }
435 previous_blit_pos = blit_pos; 456 previous_blit_pos = blit_pos;
436 457
437 // Step 2: find the last clear from the WebGL blit. This will be the 458 // Step 2: find the last clear from the WebGL blit. This will be the
438 // value of the latest mouse input that has affected this swap. 459 // value of the latest mouse input that has affected this swap.
439 size_t clear_pos = 0; 460 size_t clear_pos = 0;
440 EXPECT_TRUE(FindLastOf(events, query_clears_, blit_pos, &clear_pos)); 461 EXPECT_TRUE(FindLastOf(events, query_clears_, blit_pos, &clear_pos));
441 mouse_x = events[clear_pos]->GetKnownArgAsInt("red"); 462 mouse_x = events[clear_pos]->GetKnownArgAsInt("red");
442 } else if (mode_ == kSoftware) { 463 } else if (mode_ == kSoftware) {
443 // The software path gets the mouse_x directly from the DIB colors. 464 // The software path gets the mouse_x directly from the DIB colors.
444 mouse_x = events[i]->GetKnownArgAsInt("color"); 465 mouse_x = events[begin_swap_pos]->GetKnownArgAsInt("color");
445 } 466 }
446 467
447 // Find the corresponding mouse input. 468 // Find the corresponding mouse input.
448 size_t input_pos = 0; 469 size_t input_pos = 0;
449 Query query_mouse_event = query_inputs_ && 470 Query query_mouse_event = query_inputs_ &&
450 Query::EventArg("x") == Query::Int(mouse_x); 471 Query::EventArg("x") == Query::Int(mouse_x);
451 EXPECT_TRUE(FindLastOf(events, query_mouse_event, i, &input_pos)); 472 EXPECT_TRUE(FindLastOf(events, query_mouse_event, begin_swap_pos,
473 &input_pos));
452 474
453 // Step 4: Find the nearest onscreen SwapBuffers to this input event. 475 // Step 4: Find the nearest onscreen SwapBuffers to this input event.
454 size_t closest_swap = 0; 476 size_t closest_swap_to_input = 0;
455 size_t second_closest_swap = 0; 477 size_t second_closest_swap = 0;
456 EXPECT_TRUE(FindClosest(events, query_swaps_, input_pos, 478 EXPECT_TRUE(FindClosest(events, query_end_swaps_, input_pos,
457 &closest_swap, &second_closest_swap)); 479 &closest_swap_to_input, &second_closest_swap));
458 int latency = CountMatches(events, query_swaps_, closest_swap, i); 480
481 // Calculate latency by counting the number of swaps between the input
482 // event and the corresponding on-screen end-of-swap.
483 int latency = CountMatches(events, query_end_swaps_,
484 closest_swap_to_input, end_swap_pos);
459 latencies.push_back(latency); 485 latencies.push_back(latency);
460 if (verbose_) 486 if (verbose_)
461 printf(" %03d: %d\n", swap_count, latency); 487 printf(" %03d: %d\n", swap_count, latency);
462 else 488 else
463 printf(" %d", latency); 489 printf(" %d", latency);
464 } 490 }
465 } 491 }
466 } 492 }
467 printf("\n"); 493 printf("\n");
468 494
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 test_url += "&canvasWidth=" + base::IntToString(kWebGLCanvasWidth); 556 test_url += "&canvasWidth=" + base::IntToString(kWebGLCanvasWidth);
531 test_url += "&clearColorGreen=" + base::IntToString(kClearColorGreen); 557 test_url += "&clearColorGreen=" + base::IntToString(kClearColorGreen);
532 test_url += "&delayTimeMS=" + base::IntToString(delay_time_us_ / 1000); 558 test_url += "&delayTimeMS=" + base::IntToString(delay_time_us_ / 1000);
533 test_url += "&y=" + base::IntToString(kMouseY); 559 test_url += "&y=" + base::IntToString(kMouseY);
534 return test_url + GetUrlModeString(flags); 560 return test_url + GetUrlModeString(flags);
535 } 561 }
536 562
537 void LatencyTest::GetMeanFrameTimeMicros(int* frame_time) const { 563 void LatencyTest::GetMeanFrameTimeMicros(int* frame_time) const {
538 TraceEventVector events; 564 TraceEventVector events;
539 // Search for compositor swaps (or UpdateRects in the software path). 565 // Search for compositor swaps (or UpdateRects in the software path).
540 analyzer_->FindEvents(query_swaps_, &events); 566 analyzer_->FindEvents(query_end_swaps_, &events);
541 RateStats stats; 567 RateStats stats;
542 ASSERT_TRUE(GetRateStats(events, &stats, NULL)); 568 ASSERT_TRUE(GetRateStats(events, &stats, NULL));
543 569
544 // Check that the number of swaps is close to kNumFrames. 570 // Check that the number of swaps is close to kNumFrames.
545 EXPECT_LT(num_frames_ - num_frames_ / 4, static_cast<int>(events.size())); 571 EXPECT_LT(num_frames_ - num_frames_ / 4, static_cast<int>(events.size()));
546 *frame_time = static_cast<int>(stats.mean_us); 572 *frame_time = static_cast<int>(stats.mean_us);
547 } 573 }
548 574
549 void LatencyTest::SendInput() { 575 void LatencyTest::SendInput() {
550 content::RenderViewHost* rvh = browser()->GetSelectedTabContentsWrapper()-> 576 content::RenderViewHost* rvh = browser()->GetSelectedTabContentsWrapper()->
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 INSTANTIATE_TEST_CASE_P(, LatencyTest, ::testing::Values( 640 INSTANTIATE_TEST_CASE_P(, LatencyTest, ::testing::Values(
615 0, 641 0,
616 kInputHeavy, 642 kInputHeavy,
617 kInputHeavy | kInputDirty | kRafHeavy, 643 kInputHeavy | kInputDirty | kRafHeavy,
618 kInputHeavy | kInputDirty | kRafHeavy | kPaintHeavy, 644 kInputHeavy | kInputDirty | kRafHeavy | kPaintHeavy,
619 kInputDirty | kPaintHeavy, 645 kInputDirty | kPaintHeavy,
620 kInputDirty | kRafHeavy | kPaintHeavy 646 kInputDirty | kRafHeavy | kPaintHeavy
621 )); 647 ));
622 648
623 } // namespace 649 } // namespace
OLDNEW
« no previous file with comments | « no previous file | content/browser/renderer_host/render_widget_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698