Commit 705e7518 authored by Michael Lee's avatar Michael Lee Committed by facebook-github-bot-3

Split tests into test and benchmarks.

Summary:Split up

  io/test/IOBufCursorTest
  test/BitsTest
  test/CacheLocalityTest
  test/CallOnceTest
  test/ConvTest
  test/LoggingTest
  test/MemoryIdlerTest
  test/RandomTest
  test/ThreadLocalTest

Reviewed By: yfeldblum

Differential Revision: D2973132

fb-gh-sync-id: 9dadbdf49a31e82c3a2e34c2fdb6a2b47aa0928d
shipit-source-id: 9dadbdf49a31e82c3a2e34c2fdb6a2b47aa0928d
parent 68b1410c
......@@ -266,6 +266,7 @@ nobase_follyinclude_HEADERS = \
Portability.h \
portability/Constexpr.h \
portability/Environment.h \
portability/GFlags.h \
portability/Syscall.h \
portability/SysUio.h \
Preprocessor.h \
......
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/IOBuf.h>
#include <folly/Benchmark.h>
#include <folly/Format.h>
#include <folly/Range.h>
#include <folly/io/Cursor.h>
#include <folly/io/Cursor-defs.h>
DECLARE_bool(benchmark);
using folly::ByteRange;
using folly::format;
using folly::IOBuf;
using folly::StringPiece;
using std::unique_ptr;
using namespace folly::io;
int benchmark_size = 1000;
unique_ptr<IOBuf> iobuf_benchmark;
unique_ptr<IOBuf> iobuf_read_benchmark;
template <class CursClass>
void runBenchmark() {
CursClass c(iobuf_benchmark.get());
for (int i = 0; i < benchmark_size; i++) {
c.write((uint8_t)0);
}
}
BENCHMARK(rwPrivateCursorBenchmark, iters) {
while (iters--) {
runBenchmark<RWPrivateCursor>();
}
}
BENCHMARK(rwUnshareCursorBenchmark, iters) {
while (iters--) {
runBenchmark<RWUnshareCursor>();
}
}
BENCHMARK(cursorBenchmark, iters) {
while (iters--) {
Cursor c(iobuf_read_benchmark.get());
for (int i = 0; i < benchmark_size; i++) {
c.read<uint8_t>();
}
}
}
BENCHMARK(skipBenchmark, iters) {
while (iters--) {
Cursor c(iobuf_read_benchmark.get());
for (int i = 0; i < benchmark_size; i++) {
c.peek();
c.skip(1);
}
}
}
// fbmake opt
// _bin/folly/experimental/io/test/iobuf_cursor_test -benchmark
//
// Benchmark Iters Total t t/iter iter/sec
// ---------------------------------------------------------------------------
// rwPrivateCursorBenchmark 100000 142.9 ms 1.429 us 683.5 k
// rwUnshareCursorBenchmark 100000 309.3 ms 3.093 us 315.7 k
// cursorBenchmark 100000 741.4 ms 7.414 us 131.7 k
// skipBenchmark 100000 738.9 ms 7.389 us 132.2 k
//
// uname -a:
//
// Linux dev2159.snc6.facebook.com 2.6.33-7_fbk15_104e4d0 #1 SMP
// Tue Oct 19 22:40:30 PDT 2010 x86_64 x86_64 x86_64 GNU/Linux
//
// 72GB RAM, 2 CPUs (Intel(R) Xeon(R) CPU L5630 @ 2.13GHz)
// hyperthreading disabled
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
iobuf_benchmark = IOBuf::create(benchmark_size);
iobuf_benchmark->append(benchmark_size);
iobuf_read_benchmark = IOBuf::create(1);
for (int i = 0; i < benchmark_size; i++) {
unique_ptr<IOBuf> iobuf2(IOBuf::create(1));
iobuf2->append(1);
iobuf_read_benchmark->prependChain(std::move(iobuf2));
}
folly::runBenchmarks();
return 0;
}
......@@ -16,16 +16,12 @@
#include <folly/io/IOBuf.h>
#include <gflags/gflags.h>
#include <boost/random.hpp>
#include <gtest/gtest.h>
#include <folly/Benchmark.h>
#include <folly/Format.h>
#include <folly/Range.h>
#include <folly/io/Cursor.h>
#include <folly/io/Cursor-defs.h>
DECLARE_bool(benchmark);
#include <gtest/gtest.h>
using folly::ByteRange;
using folly::format;
......@@ -779,90 +775,3 @@ TEST(IOBuf, StringOperations) {
EXPECT_STREQ("hello", curs.readFixedString(5).c_str());
}
}
int benchmark_size = 1000;
unique_ptr<IOBuf> iobuf_benchmark;
unique_ptr<IOBuf> iobuf_read_benchmark;
template <class CursClass>
void runBenchmark() {
CursClass c(iobuf_benchmark.get());
for(int i = 0; i < benchmark_size; i++) {
c.write((uint8_t)0);
}
}
BENCHMARK(rwPrivateCursorBenchmark, iters) {
while (iters--) {
runBenchmark<RWPrivateCursor>();
}
}
BENCHMARK(rwUnshareCursorBenchmark, iters) {
while (iters--) {
runBenchmark<RWUnshareCursor>();
}
}
BENCHMARK(cursorBenchmark, iters) {
while (iters--) {
Cursor c(iobuf_read_benchmark.get());
for(int i = 0; i < benchmark_size ; i++) {
c.read<uint8_t>();
}
}
}
BENCHMARK(skipBenchmark, iters) {
while (iters--) {
Cursor c(iobuf_read_benchmark.get());
for(int i = 0; i < benchmark_size ; i++) {
c.peek();
c.skip(1);
}
}
}
// fbmake opt
// _bin/folly/experimental/io/test/iobuf_cursor_test -benchmark
//
// Benchmark Iters Total t t/iter iter/sec
// ---------------------------------------------------------------------------
// rwPrivateCursorBenchmark 100000 142.9 ms 1.429 us 683.5 k
// rwUnshareCursorBenchmark 100000 309.3 ms 3.093 us 315.7 k
// cursorBenchmark 100000 741.4 ms 7.414 us 131.7 k
// skipBenchmark 100000 738.9 ms 7.389 us 132.2 k
//
// uname -a:
//
// Linux dev2159.snc6.facebook.com 2.6.33-7_fbk15_104e4d0 #1 SMP
// Tue Oct 19 22:40:30 PDT 2010 x86_64 x86_64 x86_64 GNU/Linux
//
// 72GB RAM, 2 CPUs (Intel(R) Xeon(R) CPU L5630 @ 2.13GHz)
// hyperthreading disabled
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
auto ret = RUN_ALL_TESTS();
if (ret == 0 && FLAGS_benchmark) {
iobuf_benchmark = IOBuf::create(benchmark_size);
iobuf_benchmark->append(benchmark_size);
iobuf_read_benchmark = IOBuf::create(1);
for (int i = 0; i < benchmark_size; i++) {
unique_ptr<IOBuf> iobuf2(IOBuf::create(1));
iobuf2->append(1);
iobuf_read_benchmark->prependChain(std::move(iobuf2));
}
folly::runBenchmarks();
}
return ret;
}
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOLLY_GFLAGS_H_
#define FOLLY_GFLAGS_H_
#include <folly/Portability.h>
#if FOLLY_HAVE_LIBGFLAGS
#include <gflags/gflags.h>
#else
#define DEFINE_int32(_name, _default, _description) int FLAGS_##_name = _default
#endif
#endif
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// @author Tudor Bosman (tudorb@fb.com)
#include <folly/Bits.h>
#include <folly/Benchmark.h>
using namespace folly;
BENCHMARK(nextPowTwoClz, iters) {
for (unsigned long i = 0; i < iters; ++i) {
auto x = folly::nextPowTwo(iters);
folly::doNotOptimizeAway(x);
}
}
BENCHMARK_DRAW_LINE();
BENCHMARK(isPowTwo, iters) {
bool b;
for (unsigned long i = 0; i < iters; ++i) {
b = folly::isPowTwo(i);
folly::doNotOptimizeAway(b);
}
}
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}
/*
Benchmarks run on dual Xeon X5650's @ 2.67GHz w/hyperthreading enabled
(12 physical cores, 12 MB cache, 72 GB RAM)
Benchmark Iters Total t t/iter iter/sec
------------------------------------------------------------------------------
* nextPowTwoClz 1000000 1.659 ms 1.659 ns 574.8 M
*/
......@@ -16,9 +16,8 @@
// @author Tudor Bosman (tudorb@fb.com)
#include <gflags/gflags.h>
#include <folly/Bits.h>
#include <folly/Benchmark.h>
#include <gtest/gtest.h>
using namespace folly;
......@@ -117,13 +116,6 @@ TEST(Bits, nextPowTwoClz) {
testPowTwo(nextPowTwo);
}
BENCHMARK(nextPowTwoClz, iters) {
for (unsigned long i = 0; i < iters; ++i) {
auto x = folly::nextPowTwo(iters);
folly::doNotOptimizeAway(x);
}
}
TEST(Bits, isPowTwo) {
EXPECT_FALSE(isPowTwo(0u));
EXPECT_TRUE(isPowTwo(1ul));
......@@ -146,37 +138,9 @@ TEST(Bits, isPowTwo) {
EXPECT_FALSE(isPowTwo((1ull<<63) + 1));
}
BENCHMARK_DRAW_LINE();
BENCHMARK(isPowTwo, iters) {
bool b;
for (unsigned long i = 0; i < iters; ++i) {
b = folly::isPowTwo(i);
folly::doNotOptimizeAway(b);
}
}
TEST(Bits, popcount) {
EXPECT_EQ(0, popcount(0U));
EXPECT_EQ(1, popcount(1U));
EXPECT_EQ(32, popcount(uint32_t(-1)));
EXPECT_EQ(64, popcount(uint64_t(-1)));
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
auto ret = RUN_ALL_TESTS();
if (!ret && FLAGS_benchmark) {
folly::runBenchmarks();
}
return ret;
}
/*
Benchmarks run on dual Xeon X5650's @ 2.67GHz w/hyperthreading enabled
(12 physical cores, 12 MB cache, 72 GB RAM)
Benchmark Iters Total t t/iter iter/sec
------------------------------------------------------------------------------
* nextPowTwoClz 1000000 1.659 ms 1.659 ns 574.8 M
*/
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/CallOnce.h>
#include <deque>
#include <mutex>
#include <thread>
#include <folly/Benchmark.h>
#include <glog/logging.h>
DEFINE_int32(threads, 16, "benchmark concurrency");
template <typename CallOnceFunc>
void bm_impl(CallOnceFunc&& fn, int64_t iters) {
std::deque<std::thread> threads;
for (int i = 0; i < FLAGS_threads; ++i) {
threads.emplace_back([&fn, iters] {
for (int64_t j = 0; j < iters; ++j) {
fn();
}
});
}
for (std::thread& t : threads) {
t.join();
}
}
BENCHMARK(StdCallOnceBench, iters) {
std::once_flag flag;
int out = 0;
bm_impl([&] { std::call_once(flag, [&] { ++out; }); }, iters);
CHECK_EQ(1, out);
}
BENCHMARK(FollyCallOnceBench, iters) {
folly::once_flag flag;
int out = 0;
bm_impl([&] { folly::call_once(flag, [&] { ++out; }); }, iters);
CHECK_EQ(1, out);
}
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}
......@@ -18,9 +18,9 @@
#include <mutex>
#include <thread>
#include <folly/Benchmark.h>
#include <folly/CallOnce.h>
#include <gflags/gflags.h>
#include <folly/portability/GFlags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
......@@ -41,20 +41,6 @@ void bm_impl(CallOnceFunc&& fn, int64_t iters) {
}
}
BENCHMARK(StdCallOnceBench, iters) {
std::once_flag flag;
int out = 0;
bm_impl([&] { std::call_once(flag, [&] { ++out; }); }, iters);
ASSERT_EQ(1, out);
}
BENCHMARK(FollyCallOnceBench, iters) {
folly::once_flag flag;
int out = 0;
bm_impl([&] { folly::call_once(flag, [&] { ++out; }); }, iters);
ASSERT_EQ(1, out);
}
TEST(FollyCallOnce, Simple) {
folly::once_flag flag;
auto fn = [&](int* outp) { ++*outp; };
......@@ -72,14 +58,3 @@ TEST(FollyCallOnce, Stress) {
ASSERT_EQ(1, out);
}
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_benchmark) {
folly::runBenchmarksOnFlag();
return 0;
} else {
return RUN_ALL_TESTS();
}
}
This diff is collapsed.
This diff is collapsed.
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/Logging.h>
#include <folly/Benchmark.h>
#include <vector>
BENCHMARK(skip_overhead, iter) {
auto prev = FLAGS_minloglevel;
FLAGS_minloglevel = 2;
for (unsigned i = 0; i < iter; ++i) {
FB_LOG_EVERY_MS(INFO, 1000) << "every 1s";
}
FLAGS_minloglevel = prev;
}
BENCHMARK(dev_null_log_overhead, iter) {
auto prev = FLAGS_minloglevel;
FLAGS_minloglevel = 2;
for (unsigned i = 0; i < iter; ++i) {
FB_LOG_EVERY_MS(INFO, -1) << "every -1ms";
}
FLAGS_minloglevel = prev;
}
// ============================================================================
// folly/test/LoggingTest.cpp relative time/iter iters/s
// ============================================================================
// skip_overhead 36.37ns 27.49M
// dev_null_log_overhead 2.61us 382.57K
// ============================================================================
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}
......@@ -15,9 +15,9 @@
*/
#include <folly/Logging.h>
#include <gflags/gflags.h>
#include <gtest/gtest.h>
#include <folly/Benchmark.h>
#include <vector>
TEST(LogEveryMs, basic) {
......@@ -50,43 +50,3 @@ TEST(LogEveryMs, zero) {
EXPECT_EQ(10, count);
}
BENCHMARK(skip_overhead, iter) {
auto prev = FLAGS_minloglevel;
FLAGS_minloglevel = 2;
for (unsigned i = 0; i < iter; ++i) {
FB_LOG_EVERY_MS(INFO, 1000) << "every 1s";
}
FLAGS_minloglevel = prev;
}
BENCHMARK(dev_null_log_overhead, iter) {
auto prev = FLAGS_minloglevel;
FLAGS_minloglevel = 2;
for (unsigned i = 0; i < iter; ++i) {
FB_LOG_EVERY_MS(INFO, -1) << "every -1ms";
}
FLAGS_minloglevel = prev;
}
// ============================================================================
// folly/test/LoggingTest.cpp relative time/iter iters/s
// ============================================================================
// skip_overhead 36.37ns 27.49M
// dev_null_log_overhead 2.61us 382.57K
// ============================================================================
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
auto rv = RUN_ALL_TESTS();
if (!rv && FLAGS_benchmark) {
folly::runBenchmarks();
}
return rv;
}
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/detail/MemoryIdler.h>
#include <folly/Benchmark.h>
using namespace folly::detail;
BENCHMARK(releaseStack, iters) {
for (size_t i = 0; i < iters; ++i) {
MemoryIdler::unmapUnusedStack();
}
}
BENCHMARK(releaseMallocTLS, iters) {
for (size_t i = 0; i < iters; ++i) {
MemoryIdler::flushLocalMallocCaches();
}
}
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}
......@@ -15,15 +15,16 @@
*/
#include <folly/detail/MemoryIdler.h>
#include <folly/Baton.h>
#include <memory>
#include <thread>
#include <assert.h>
#include <semaphore.h>
#include <gflags/gflags.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <folly/Benchmark.h>
using namespace folly;
using namespace folly::detail;
......@@ -182,27 +183,3 @@ TEST(MemoryIdler, futexWaitNeverFlush) {
EXPECT_TRUE((MemoryIdler::futexWait<MockAtom, MockClock>(
fut, 1, -1, MockClock::duration::max())));
}
BENCHMARK(releaseStack, iters) {
for (size_t i = 0; i < iters; ++i) {
MemoryIdler::unmapUnusedStack();
}
}
BENCHMARK(releaseMallocTLS, iters) {
for (size_t i = 0; i < iters; ++i) {
MemoryIdler::flushLocalMallocCaches();
}
}
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
auto rv = RUN_ALL_TESTS();
if (!rv && FLAGS_benchmark) {
folly::runBenchmarks();
}
return rv;
}
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/Random.h>
#include <folly/Benchmark.h>
#include <folly/Foreach.h>
#include <folly/Range.h>
#include <glog/logging.h>
#include <algorithm>
#include <thread>
#include <vector>
#include <random>
using namespace folly;
BENCHMARK(minstdrand, n) {
BenchmarkSuspender braces;
std::random_device rd;
std::minstd_rand rng(rd());
braces.dismiss();
FOR_EACH_RANGE(i, 0, n) { doNotOptimizeAway(rng()); }
}
BENCHMARK(mt19937, n) {
BenchmarkSuspender braces;
std::random_device rd;
std::mt19937 rng(rd());
braces.dismiss();
FOR_EACH_RANGE(i, 0, n) { doNotOptimizeAway(rng()); }
}
BENCHMARK(threadprng, n) {
BenchmarkSuspender braces;
ThreadLocalPRNG tprng;
tprng();
braces.dismiss();
FOR_EACH_RANGE(i, 0, n) { doNotOptimizeAway(tprng()); }
}
BENCHMARK(RandomDouble) { doNotOptimizeAway(Random::randDouble01()); }
BENCHMARK(Random32) { doNotOptimizeAway(Random::rand32()); }
BENCHMARK(Random32Num) { doNotOptimizeAway(Random::rand32(100)); }
BENCHMARK(Random64) { doNotOptimizeAway(Random::rand64()); }
BENCHMARK(Random64Num) { doNotOptimizeAway(Random::rand64(100ul << 32)); }
BENCHMARK(Random64OneIn) { doNotOptimizeAway(Random::oneIn(100)); }
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}
......@@ -15,9 +15,6 @@
*/
#include <folly/Random.h>
#include <folly/Range.h>
#include <folly/Benchmark.h>
#include <folly/Foreach.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
......@@ -67,56 +64,3 @@ TEST(Random, MultiThreaded) {
EXPECT_LT(seeds[i], seeds[i+1]);
}
}
BENCHMARK(minstdrand, n) {
BenchmarkSuspender braces;
std::random_device rd;
std::minstd_rand rng(rd());
braces.dismiss();
FOR_EACH_RANGE (i, 0, n) {
doNotOptimizeAway(rng());
}
}
BENCHMARK(mt19937, n) {
BenchmarkSuspender braces;
std::random_device rd;
std::mt19937 rng(rd());
braces.dismiss();
FOR_EACH_RANGE (i, 0, n) {
doNotOptimizeAway(rng());
}
}
BENCHMARK(threadprng, n) {
BenchmarkSuspender braces;
ThreadLocalPRNG tprng;
tprng();
braces.dismiss();
FOR_EACH_RANGE (i, 0, n) {
doNotOptimizeAway(tprng());
}
}
BENCHMARK(RandomDouble) { doNotOptimizeAway(Random::randDouble01()); }
BENCHMARK(Random32) { doNotOptimizeAway(Random::rand32()); }
BENCHMARK(Random32Num) { doNotOptimizeAway(Random::rand32(100)); }
BENCHMARK(Random64) { doNotOptimizeAway(Random::rand64()); }
BENCHMARK(Random64Num) { doNotOptimizeAway(Random::rand64(100ul << 32)); }
BENCHMARK(Random64OneIn) { doNotOptimizeAway(Random::oneIn(100)); }
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_benchmark) {
folly::runBenchmarks();
}
return RUN_ALL_TESTS();
}
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/ThreadLocal.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <limits.h>
#include <map>
#include <mutex>
#include <set>
#include <thread>
#include <unordered_map>
#include <boost/thread/tss.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <folly/Benchmark.h>
#include <folly/experimental/io/FsUtil.h>
using namespace folly;
// Simple reference implementation using pthread_get_specific
template <typename T>
class PThreadGetSpecific {
public:
PThreadGetSpecific() : key_(0) { pthread_key_create(&key_, OnThreadExit); }
T* get() const { return static_cast<T*>(pthread_getspecific(key_)); }
void reset(T* t) {
delete get();
pthread_setspecific(key_, t);
}
static void OnThreadExit(void* obj) { delete static_cast<T*>(obj); }
private:
pthread_key_t key_;
};
DEFINE_int32(numThreads, 8, "Number simultaneous threads for benchmarks.");
#define REG(var) \
BENCHMARK(FB_CONCATENATE(BM_mt_, var), iters) { \
const int itersPerThread = iters / FLAGS_numThreads; \
std::vector<std::thread> threads; \
for (int i = 0; i < FLAGS_numThreads; ++i) { \
threads.push_back(std::thread([&]() { \
var.reset(new int(0)); \
for (int i = 0; i < itersPerThread; ++i) { \
++(*var.get()); \
} \
})); \
} \
for (auto& t : threads) { \
t.join(); \
} \
}
ThreadLocalPtr<int> tlp;
REG(tlp);
PThreadGetSpecific<int> pthread_get_specific;
REG(pthread_get_specific);
boost::thread_specific_ptr<int> boost_tsp;
REG(boost_tsp);
BENCHMARK_DRAW_LINE();
int main(int argc, char** argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
gflags::SetCommandLineOptionWithMode(
"bm_max_iters", "100000000", gflags::SET_FLAG_IF_DEFAULT);
folly::runBenchmarks();
return 0;
}
/*
Ran with 24 threads on dual 12-core Xeon(R) X5650 @ 2.67GHz with 12-MB caches
Benchmark Iters Total t t/iter iter/sec
------------------------------------------------------------------------------
* BM_mt_tlp 100000000 39.88 ms 398.8 ps 2.335 G
+5.91% BM_mt_pthread_get_specific 100000000 42.23 ms 422.3 ps 2.205 G
+ 295% BM_mt_boost_tsp 100000000 157.8 ms 1.578 ns 604.5 M
------------------------------------------------------------------------------
*/
......@@ -32,12 +32,9 @@
#include <thread>
#include <unordered_map>
#include <boost/thread/tss.hpp>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <folly/Benchmark.h>
#include <folly/Baton.h>
#include <folly/experimental/io/FsUtil.h>
......@@ -596,91 +593,3 @@ TEST(ThreadLocal, UnregisterClassHasConstExprCtor) {
// yep!
SUCCEED();
}
// clang is unable to compile this code unless in c++14 mode.
#if __cplusplus >= 201402L
namespace {
// This will fail to compile unless ThreadLocal{Ptr} has a constexpr
// default constructor. This ensures that ThreadLocal is safe to use in
// static constructors without worrying about initialization order
class ConstexprThreadLocalCompile {
ThreadLocal<int> a_;
ThreadLocalPtr<int> b_;
constexpr ConstexprThreadLocalCompile() {}
};
}
#endif
// Simple reference implementation using pthread_get_specific
template<typename T>
class PThreadGetSpecific {
public:
PThreadGetSpecific() : key_(0) {
pthread_key_create(&key_, OnThreadExit);
}
T* get() const {
return static_cast<T*>(pthread_getspecific(key_));
}
void reset(T* t) {
delete get();
pthread_setspecific(key_, t);
}
static void OnThreadExit(void* obj) {
delete static_cast<T*>(obj);
}
private:
pthread_key_t key_;
};
DEFINE_int32(numThreads, 8, "Number simultaneous threads for benchmarks.");
#define REG(var) \
BENCHMARK(FB_CONCATENATE(BM_mt_, var), iters) { \
const int itersPerThread = iters / FLAGS_numThreads; \
std::vector<std::thread> threads; \
for (int i = 0; i < FLAGS_numThreads; ++i) { \
threads.push_back(std::thread([&]() { \
var.reset(new int(0)); \
for (int i = 0; i < itersPerThread; ++i) { \
++(*var.get()); \
} \
})); \
} \
for (auto& t : threads) { \
t.join(); \
} \
}
ThreadLocalPtr<int> tlp;
REG(tlp);
PThreadGetSpecific<int> pthread_get_specific;
REG(pthread_get_specific);
boost::thread_specific_ptr<int> boost_tsp;
REG(boost_tsp);
BENCHMARK_DRAW_LINE();
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);
gflags::SetCommandLineOptionWithMode(
"bm_max_iters", "100000000", gflags::SET_FLAG_IF_DEFAULT
);
if (FLAGS_benchmark) {
folly::runBenchmarks();
}
return RUN_ALL_TESTS();
}
/*
Ran with 24 threads on dual 12-core Xeon(R) X5650 @ 2.67GHz with 12-MB caches
Benchmark Iters Total t t/iter iter/sec
------------------------------------------------------------------------------
* BM_mt_tlp 100000000 39.88 ms 398.8 ps 2.335 G
+5.91% BM_mt_pthread_get_specific 100000000 42.23 ms 422.3 ps 2.205 G
+ 295% BM_mt_boost_tsp 100000000 157.8 ms 1.578 ns 604.5 M
------------------------------------------------------------------------------
*/
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