Home | History | Annotate | Download | only in microbench
      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);