Commit de813bdb authored by Etienne Pierre-doray's avatar Etienne Pierre-doray Committed by Commit Bot

[TLS]: Implement tls base_perftests.

Add perftests to compute read + write throughput. This CL only implements
benchmarks for ThreadLocalStorage. PlatformThreadLocalStorage will be added as
a follow-up.

Change-Id: I80de0bcb3a31e771646c942413aa156ecf960798
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1643469
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#666213}
parent 8d80db93
......@@ -2216,6 +2216,7 @@ test("base_perftests") {
"strings/string_util_perftest.cc",
"task/sequence_manager/sequence_manager_perftest.cc",
"task/thread_pool/thread_pool_perftest.cc",
"threading/thread_local_storage_perftest.cc",
# "test/run_all_unittests.cc",
"json/json_perftest.cc",
......
// Copyright 2019 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 <stddef.h>
#include <memory>
#include <vector>
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind_test_util.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread_local_storage.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_test.h"
namespace base {
namespace internal {
namespace {
// A thread that waits for the caller to signal an event before proceeding to
// call action.Run().
class TLSThread : public SimpleThread {
public:
// Creates a PostingThread that waits on |start_event| before calling
// action.Run().
TLSThread(WaitableEvent* start_event,
base::OnceClosure action,
base::OnceClosure completion)
: SimpleThread("TLSThread"),
start_event_(start_event),
action_(std::move(action)),
completion_(std::move(completion)) {
Start();
}
void Run() override {
start_event_->Wait();
std::move(action_).Run();
std::move(completion_).Run();
}
private:
WaitableEvent* const start_event_;
base::OnceClosure action_;
base::OnceClosure completion_;
DISALLOW_COPY_AND_ASSIGN(TLSThread);
};
class ThreadLocalStoragePerfTest : public testing::Test {
public:
protected:
ThreadLocalStoragePerfTest() = default;
~ThreadLocalStoragePerfTest() override = default;
template <class Read, class Write>
void Benchmark(const std::string& trace,
Read read,
Write write,
size_t num_operation,
size_t num_threads) {
write(2);
BenchmarkImpl("TLS read throughput", trace,
base::BindLambdaForTesting([&]() {
volatile intptr_t total = 0;
for (size_t i = 0; i < num_operation; ++i)
total += read();
}),
num_operation, num_threads);
BenchmarkImpl("TLS write throughput", trace,
base::BindLambdaForTesting([&]() {
for (size_t i = 0; i < num_operation; ++i)
write(i);
}),
num_operation, num_threads);
BenchmarkImpl("TLS read-write throughput", trace,
base::BindLambdaForTesting([&]() {
for (size_t i = 0; i < num_operation; ++i)
write(read() + 1);
}),
num_operation, num_threads);
}
void BenchmarkImpl(const std::string& measurment,
const std::string& trace,
base::RepeatingClosure action,
size_t num_operation,
size_t num_threads) {
WaitableEvent start_thread;
WaitableEvent complete_thread;
base::RepeatingClosure done = BarrierClosure(
num_threads,
base::BindLambdaForTesting([&]() { complete_thread.Signal(); }));
std::vector<std::unique_ptr<TLSThread>> threads;
for (size_t i = 0; i < num_threads; ++i) {
threads.emplace_back(
std::make_unique<TLSThread>(&start_thread, action, done));
}
TimeTicks operation_start = TimeTicks::Now();
start_thread.Signal();
complete_thread.Wait();
TimeDelta operation_duration = TimeTicks::Now() - operation_start;
for (auto& thread : threads)
thread->Join();
perf_test::PrintResult(
measurment, "", trace,
num_operation /
static_cast<double>(operation_duration.InMilliseconds()),
"operations/ms", true);
}
private:
DISALLOW_COPY_AND_ASSIGN(ThreadLocalStoragePerfTest);
};
} // namespace
TEST_F(ThreadLocalStoragePerfTest, ThreadLocalStorage) {
ThreadLocalStorage::Slot tls;
auto read = [&]() { return reinterpret_cast<intptr_t>(tls.Get()); };
auto write = [&](intptr_t value) { tls.Set(reinterpret_cast<void*>(value)); };
Benchmark("ThreadLocalStorage", read, write, 1000000, 1);
Benchmark("ThreadLocalStorage 4 threads", read, write, 1000000, 4);
}
} // namespace internal
} // namespace base
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment