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: 34 explicit TrivialProcessor(TaskManager* manager) : TaskProcessor(manager) {} 35 virtual ~TrivialProcessor() {} 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 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 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 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 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 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);