summaryrefslogtreecommitdiffstats
path: root/cc/debug
diff options
context:
space:
mode:
authordominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-13 19:40:58 +0000
committerdominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-13 19:40:58 +0000
commit29d39a4adb6f9b2a4e05bb3f95140df2e3957ec7 (patch)
treeed44e1e28e3bbe7772fd44843bab4c226271e4a7 /cc/debug
parent08035b96da9bb56a4a857f99756ae47743f2975b (diff)
downloadchromium_src-29d39a4adb6f9b2a4e05bb3f95140df2e3957ec7.zip
chromium_src-29d39a4adb6f9b2a4e05bb3f95140df2e3957ec7.tar.gz
chromium_src-29d39a4adb6f9b2a4e05bb3f95140df2e3957ec7.tar.bz2
Use LapTimer in rasterize_and_record micro benchmark.
Timing record or rasterize on very small layers can be problematic. The operations are very short and timing them individually can lead to quantization. Use a LapTimer to run the operations we're timing for at least a specified amount of time to avoid this problem. Moves LapTimer from cc/test to cc/debug so it's accessible outside of testing code. BUG= Review URL: https://codereview.chromium.org/279183002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270170 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/debug')
-rw-r--r--cc/debug/lap_timer.cc81
-rw-r--r--cc/debug/lap_timer.h64
-rw-r--r--cc/debug/rasterize_and_record_benchmark.cc30
-rw-r--r--cc/debug/rasterize_and_record_benchmark_impl.cc49
4 files changed, 193 insertions, 31 deletions
diff --git a/cc/debug/lap_timer.cc b/cc/debug/lap_timer.cc
new file mode 100644
index 0000000..27aaf34
--- /dev/null
+++ b/cc/debug/lap_timer.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/debug/lap_timer.h"
+
+#include "base/logging.h"
+
+namespace cc {
+
+namespace {
+
+base::TimeTicks Now() {
+ return base::TimeTicks::IsThreadNowSupported()
+ ? base::TimeTicks::ThreadNow()
+ : base::TimeTicks::HighResNow();
+}
+
+} // namespace
+
+LapTimer::LapTimer(int warmup_laps,
+ base::TimeDelta time_limit,
+ int check_interval)
+ : warmup_laps_(warmup_laps),
+ remaining_warmups_(0),
+ remaining_no_check_laps_(0),
+ time_limit_(time_limit),
+ check_interval_(check_interval) {
+ DCHECK_GT(check_interval, 0);
+ Reset();
+}
+
+void LapTimer::Reset() {
+ accumulator_ = base::TimeDelta();
+ num_laps_ = 0;
+ remaining_warmups_ = warmup_laps_;
+ remaining_no_check_laps_ = check_interval_;
+ Start();
+}
+
+void LapTimer::Start() {
+ start_time_ = Now();
+}
+
+bool LapTimer::IsWarmedUp() { return remaining_warmups_ <= 0; }
+
+void LapTimer::NextLap() {
+ if (!IsWarmedUp()) {
+ --remaining_warmups_;
+ if (IsWarmedUp()) {
+ Start();
+ }
+ return;
+ }
+ ++num_laps_;
+ --remaining_no_check_laps_;
+ if (!remaining_no_check_laps_) {
+ base::TimeTicks now = Now();
+ accumulator_ += now - start_time_;
+ start_time_ = now;
+ remaining_no_check_laps_ = check_interval_;
+ }
+}
+
+bool LapTimer::HasTimeLimitExpired() { return accumulator_ >= time_limit_; }
+
+bool LapTimer::HasTimedAllLaps() { return !(num_laps_ % check_interval_); }
+
+float LapTimer::MsPerLap() {
+ DCHECK(HasTimedAllLaps());
+ return accumulator_.InMillisecondsF() / num_laps_;
+}
+
+float LapTimer::LapsPerSecond() {
+ DCHECK(HasTimedAllLaps());
+ return num_laps_ / accumulator_.InSecondsF();
+}
+
+int LapTimer::NumLaps() { return num_laps_; }
+
+} // namespace cc
diff --git a/cc/debug/lap_timer.h b/cc/debug/lap_timer.h
new file mode 100644
index 0000000..7ec9a8c
--- /dev/null
+++ b/cc/debug/lap_timer.h
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CC_DEBUG_LAP_TIMER_H_
+#define CC_DEBUG_LAP_TIMER_H_
+
+#include "base/time/time.h"
+#include "cc/base/cc_export.h"
+
+namespace cc {
+
+// LapTimer is used to calculate average times per "Lap" in perf tests.
+// Current() reports the time since the last call to Start().
+// Store() adds the time since the last call to Start() to the accumulator, and
+// resets the start time to now. Stored() returns the accumulated time.
+// NextLap increments the lap counter, used in counting the per lap averages.
+// If you initialize the LapTimer with a non zero warmup_laps, it will ignore
+// the times for that many laps at the start.
+// If you set the time_limit then you can use HasTimeLimitExpired() to see if
+// the current accumulated time has crossed that threshold, with an optimization
+// that it only tests this every check_interval laps.
+class CC_EXPORT LapTimer {
+ public:
+ LapTimer(int warmup_laps, base::TimeDelta time_limit, int check_interval);
+ // Resets the timer back to it's starting state.
+ void Reset();
+ // Sets the start point to now.
+ void Start();
+ // Returns true if there are no more warmup laps to do.
+ bool IsWarmedUp();
+ // Advance the lap counter and update the accumulated time.
+ // The accumulated time is only updated every check_interval laps.
+ // If accumulating then the start point will also be updated.
+ void NextLap();
+ // Returns true if the stored time has exceeded the time limit specified.
+ // May cause a call to Store().
+ bool HasTimeLimitExpired();
+ // Returns true if all lap times have been timed. Only true every n'th
+ // lap, where n = check_interval.
+ bool HasTimedAllLaps();
+ // The average milliseconds per lap.
+ float MsPerLap();
+ // The number of laps per second.
+ float LapsPerSecond();
+ // The number of laps recorded.
+ int NumLaps();
+
+ private:
+ base::TimeTicks start_time_;
+ base::TimeDelta accumulator_;
+ int num_laps_;
+ int warmup_laps_;
+ int remaining_warmups_;
+ int remaining_no_check_laps_;
+ base::TimeDelta time_limit_;
+ int check_interval_;
+
+ DISALLOW_COPY_AND_ASSIGN(LapTimer);
+};
+
+} // namespace cc
+
+#endif // CC_DEBUG_LAP_TIMER_H_
diff --git a/cc/debug/rasterize_and_record_benchmark.cc b/cc/debug/rasterize_and_record_benchmark.cc
index b330e42..197fb29 100644
--- a/cc/debug/rasterize_and_record_benchmark.cc
+++ b/cc/debug/rasterize_and_record_benchmark.cc
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
+#include "cc/debug/lap_timer.h"
#include "cc/debug/rasterize_and_record_benchmark_impl.h"
#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
@@ -27,12 +28,6 @@ const int kDefaultRecordRepeatCount = 100;
const char* kModeSuffixes[Picture::RECORDING_MODE_COUNT] = {
"", "_sk_null_canvas", "_painting_disabled", "_skrecord"};
-base::TimeTicks Now() {
- return base::TimeTicks::IsThreadNowSupported()
- ? base::TimeTicks::ThreadNow()
- : base::TimeTicks::HighResNow();
-}
-
} // namespace
RasterizeAndRecordBenchmark::RasterizeAndRecordBenchmark(
@@ -121,12 +116,25 @@ void RasterizeAndRecordBenchmark::RunOnLayer(PictureLayer* layer) {
Picture::RecordingMode mode =
static_cast<Picture::RecordingMode>(mode_index);
base::TimeDelta min_time = base::TimeDelta::Max();
+
+ // Parameters for LapTimer.
+ const int kTimeLimitMillis = 1;
+ const int kWarmupRuns = 0;
+ const int kTimeCheckInterval = 1;
+
for (int i = 0; i < record_repeat_count_; ++i) {
- base::TimeTicks start = Now();
- scoped_refptr<Picture> picture = Picture::Create(
- visible_content_rect, painter, tile_grid_info, false, 0, mode);
- base::TimeTicks end = Now();
- base::TimeDelta duration = end - start;
+ // Run for a minimum amount of time to avoid problems with timer
+ // quantization when the layer is very small.
+ LapTimer timer(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval);
+ do {
+ scoped_refptr<Picture> picture = Picture::Create(
+ visible_content_rect, painter, tile_grid_info, false, 0, mode);
+ timer.NextLap();
+ } while (!timer.HasTimeLimitExpired());
+ base::TimeDelta duration =
+ base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
if (duration < min_time)
min_time = duration;
}
diff --git a/cc/debug/rasterize_and_record_benchmark_impl.cc b/cc/debug/rasterize_and_record_benchmark_impl.cc
index 48d7c34..a22c2cd 100644
--- a/cc/debug/rasterize_and_record_benchmark_impl.cc
+++ b/cc/debug/rasterize_and_record_benchmark_impl.cc
@@ -9,6 +9,7 @@
#include "base/basictypes.h"
#include "base/values.h"
+#include "cc/debug/lap_timer.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/resources/raster_worker_pool.h"
@@ -22,12 +23,6 @@ namespace {
const int kDefaultRasterizeRepeatCount = 100;
-base::TimeTicks Now() {
- return base::TimeTicks::IsThreadNowSupported()
- ? base::TimeTicks::ThreadNow()
- : base::TimeTicks::HighResNow();
-}
-
class BenchmarkRasterTask : public Task {
public:
BenchmarkRasterTask(PicturePileImpl* picture_pile,
@@ -46,24 +41,38 @@ class BenchmarkRasterTask : public Task {
PicturePileImpl* picture_pile = picture_pile_->GetCloneForDrawingOnThread(
RasterWorkerPool::GetPictureCloneIndexForCurrentThread());
+ // Parameters for LapTimer.
+ const int kTimeLimitMillis = 1;
+ const int kWarmupRuns = 0;
+ const int kTimeCheckInterval = 1;
+
for (size_t i = 0; i < repeat_count_; ++i) {
- SkBitmap bitmap;
- bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect_.width(),
- content_rect_.height()));
- SkCanvas canvas(bitmap);
- PicturePileImpl::Analysis analysis;
-
- base::TimeTicks start = Now();
- picture_pile->AnalyzeInRect(
- content_rect_, contents_scale_, &analysis, NULL);
- picture_pile->RasterToBitmap(
- &canvas, content_rect_, contents_scale_, NULL);
- base::TimeTicks end = Now();
- base::TimeDelta duration = end - start;
+ // Run for a minimum amount of time to avoid problems with timer
+ // quantization when the layer is very small.
+ LapTimer timer(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval);
+ do {
+ SkBitmap bitmap;
+ bitmap.allocPixels(SkImageInfo::MakeN32Premul(content_rect_.width(),
+ content_rect_.height()));
+ SkCanvas canvas(bitmap);
+ PicturePileImpl::Analysis analysis;
+
+ picture_pile->AnalyzeInRect(
+ content_rect_, contents_scale_, &analysis, NULL);
+ picture_pile->RasterToBitmap(
+ &canvas, content_rect_, contents_scale_, NULL);
+
+ is_solid_color_ = analysis.is_solid_color;
+
+ timer.NextLap();
+ } while (!timer.HasTimeLimitExpired());
+ base::TimeDelta duration =
+ base::TimeDelta::FromMillisecondsD(timer.MsPerLap());
if (duration < best_time_)
best_time_ = duration;
- is_solid_color_ = analysis.is_solid_color;
}
}