// Copyright 2016 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 "third_party/blink/renderer/platform/timer.h" #include "base/run_loop.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { class TimerPerfTest : public testing::Test { public: void NopTask(TimerBase*) {} void RecordStartRunTime(TimerBase*) { run_start_ = base::ThreadTicks::Now(); } void RecordEndRunTime(TimerBase*) { run_end_ = base::ThreadTicks::Now(); base::RunLoop::QuitCurrentDeprecated(); } base::ThreadTicks run_start_; base::ThreadTicks run_end_; }; TEST_F(TimerPerfTest, PostAndRunTimers) { const int kNumIterations = 10000; Vector>> timers( kNumIterations); for (int i = 0; i < kNumIterations; i++) { timers[i].reset(new TaskRunnerTimer( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::NopTask)); } TaskRunnerTimer measure_run_start( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::RecordStartRunTime); TaskRunnerTimer measure_run_end( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::RecordEndRunTime); measure_run_start.StartOneShot(TimeDelta(), FROM_HERE); base::ThreadTicks post_start = base::ThreadTicks::Now(); for (int i = 0; i < kNumIterations; i++) { timers[i]->StartOneShot(TimeDelta(), FROM_HERE); } base::ThreadTicks post_end = base::ThreadTicks::Now(); measure_run_end.StartOneShot(TimeDelta(), FROM_HERE); test::EnterRunLoop(); double posting_time = (post_end - post_start).InMicroseconds(); double posting_time_us_per_call = posting_time / static_cast(kNumIterations); LOG(INFO) << "TimerBase::startOneShot cost (us/call) " << posting_time_us_per_call << " (total " << posting_time << " us)"; LOG(INFO) << "Time to run " << kNumIterations << " trivial tasks (us) " << (run_end_ - run_start_).InMicroseconds(); } TEST_F(TimerPerfTest, PostThenCancelTenThousandTimers) { const int kNumIterations = 10000; Vector>> timers( kNumIterations); for (int i = 0; i < kNumIterations; i++) { timers[i].reset(new TaskRunnerTimer( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::NopTask)); } TaskRunnerTimer measure_run_start( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::RecordStartRunTime); TaskRunnerTimer measure_run_end( scheduler::GetSingleThreadTaskRunnerForTesting(), this, &TimerPerfTest::RecordEndRunTime); measure_run_start.StartOneShot(TimeDelta(), FROM_HERE); base::ThreadTicks post_start = base::ThreadTicks::Now(); for (int i = 0; i < kNumIterations; i++) { timers[i]->StartOneShot(TimeDelta(), FROM_HERE); } base::ThreadTicks post_end = base::ThreadTicks::Now(); measure_run_end.StartOneShot(TimeDelta(), FROM_HERE); base::ThreadTicks cancel_start = base::ThreadTicks::Now(); for (int i = 0; i < kNumIterations; i++) { timers[i]->Stop(); } base::ThreadTicks cancel_end = base::ThreadTicks::Now(); test::EnterRunLoop(); double posting_time = (post_end - post_start).InMicroseconds(); double posting_time_us_per_call = posting_time / static_cast(kNumIterations); LOG(INFO) << "TimerBase::startOneShot cost (us/call) " << posting_time_us_per_call << " (total " << posting_time << " us)"; double cancel_time = (cancel_end - cancel_start).InMicroseconds(); double cancel_time_us_per_call = cancel_time / static_cast(kNumIterations); LOG(INFO) << "TimerBase::stop cost (us/call) " << cancel_time_us_per_call << " (total " << cancel_time << " us)"; LOG(INFO) << "Time to run " << kNumIterations << " canceled tasks (us) " << (run_end_ - run_start_).InMicroseconds(); } } // namespace blink