1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <benchmark/benchmark.h>
18
19 #include "thread/Task.h"
20 #include "thread/TaskManager.h"
21 #include "thread/TaskProcessor.h"
22 #include "thread/ThreadBase.h"
23
24 #include <atomic>
25 #include <vector>
26
27 using namespace android;
28 using namespace android::uirenderer;
29
30 class TrivialTask : public Task<char> {};
31
32 class TrivialProcessor : public TaskProcessor<char> {
33 public:
TrivialProcessor(TaskManager * manager)34 explicit TrivialProcessor(TaskManager* manager) : TaskProcessor(manager) {}
~TrivialProcessor()35 virtual ~TrivialProcessor() {}
onProcess(const sp<Task<char>> & task)36 virtual void onProcess(const sp<Task<char>>& task) override {
37 TrivialTask* t = static_cast<TrivialTask*>(task.get());
38 t->setResult(reinterpret_cast<intptr_t>(t) % 16 == 0 ? 'a' : 'b');
39 }
40 };
41
42 class TestThread : public ThreadBase, public virtual RefBase {};
43
BM_TaskManager_allocateTask(benchmark::State & state)44 void BM_TaskManager_allocateTask(benchmark::State& state) {
45 std::vector<sp<TrivialTask>> tasks;
46 tasks.reserve(state.max_iterations);
47
48 while (state.KeepRunning()) {
49 tasks.emplace_back(new TrivialTask);
50 benchmark::DoNotOptimize(tasks.back());
51 }
52 }
53 BENCHMARK(BM_TaskManager_allocateTask);
54
BM_TaskManager_enqueueTask(benchmark::State & state)55 void BM_TaskManager_enqueueTask(benchmark::State& state) {
56 TaskManager taskManager;
57 sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
58 std::vector<sp<TrivialTask>> tasks;
59 tasks.reserve(state.max_iterations);
60
61 while (state.KeepRunning()) {
62 tasks.emplace_back(new TrivialTask);
63 benchmark::DoNotOptimize(tasks.back());
64 processor->add(tasks.back());
65 }
66
67 for (sp<TrivialTask>& task : tasks) {
68 task->getResult();
69 }
70 }
71 BENCHMARK(BM_TaskManager_enqueueTask);
72
BM_TaskManager_enqueueRunDeleteTask(benchmark::State & state)73 void BM_TaskManager_enqueueRunDeleteTask(benchmark::State& state) {
74 TaskManager taskManager;
75 sp<TrivialProcessor> processor(new TrivialProcessor(&taskManager));
76 std::vector<sp<TrivialTask>> tasks;
77 tasks.reserve(state.max_iterations);
78
79 while (state.KeepRunning()) {
80 tasks.emplace_back(new TrivialTask);
81 benchmark::DoNotOptimize(tasks.back());
82 processor->add(tasks.back());
83 }
84 state.ResumeTiming();
85 for (sp<TrivialTask>& task : tasks) {
86 benchmark::DoNotOptimize(task->getResult());
87 }
88 tasks.clear();
89 state.PauseTiming();
90 }
91 BENCHMARK(BM_TaskManager_enqueueRunDeleteTask);
92
BM_Thread_enqueueTask(benchmark::State & state)93 void BM_Thread_enqueueTask(benchmark::State& state) {
94 sp<TestThread> thread{new TestThread};
95 thread->start();
96
97 atomic_int counter(0);
98 int expected = 0;
99 while (state.KeepRunning()) {
100 expected++;
101 thread->queue().post([&counter]() { counter++; });
102 }
103 thread->queue().runSync([]() {});
104
105 thread->requestExit();
106 thread->join();
107 if (counter != expected) {
108 printf("Ran %d lambads, should have been %d\n", counter.load(), expected);
109 }
110 }
111 BENCHMARK(BM_Thread_enqueueTask);
112
BM_Thread_enqueueRunDeleteTask(benchmark::State & state)113 void BM_Thread_enqueueRunDeleteTask(benchmark::State& state) {
114 sp<TestThread> thread{new TestThread};
115 thread->start();
116 std::vector<std::future<int>> tasks;
117 tasks.reserve(state.max_iterations);
118
119 int expected = 0;
120 while (state.KeepRunning()) {
121 tasks.emplace_back(thread->queue().async([expected]() -> int { return expected + 1; }));
122 expected++;
123 }
124 state.ResumeTiming();
125 expected = 0;
126 for (auto& future : tasks) {
127 if (future.get() != ++expected) {
128 printf("Mismatch expected %d vs. observed %d\n", expected, future.get());
129 }
130 }
131 tasks.clear();
132 state.PauseTiming();
133 }
134 BENCHMARK(BM_Thread_enqueueRunDeleteTask);