diff options
author | dominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-13 19:40:58 +0000 |
---|---|---|
committer | dominikg@chromium.org <dominikg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-13 19:40:58 +0000 |
commit | 29d39a4adb6f9b2a4e05bb3f95140df2e3957ec7 (patch) | |
tree | ed44e1e28e3bbe7772fd44843bab4c226271e4a7 /cc/debug | |
parent | 08035b96da9bb56a4a857f99756ae47743f2975b (diff) | |
download | chromium_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.cc | 81 | ||||
-rw-r--r-- | cc/debug/lap_timer.h | 64 | ||||
-rw-r--r-- | cc/debug/rasterize_and_record_benchmark.cc | 30 | ||||
-rw-r--r-- | cc/debug/rasterize_and_record_benchmark_impl.cc | 49 |
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; } } |