/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* 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/stats/DigestBuilder.h>
#include <chrono>
#include <condition_variable>
#include <thread>
#include <boost/thread/barrier.hpp>
#include <folly/Benchmark.h>
#include <folly/Range.h>
#include <folly/lang/Keep.h>
#include <folly/portability/GFlags.h>
DEFINE_int32(digest_merge_time_ns, 5500, "Time to merge into the digest");
using namespace folly;
class FreeDigest {
public:
explicit FreeDigest(size_t = 0) {}
FreeDigest merge(Range<const double*> values) const {
auto start = std::chrono::steady_clock::now();
auto finish = start + std::chrono::nanoseconds{FLAGS_digest_merge_time_ns};
while (std::chrono::steady_clock::now() < finish) {
}
FreeDigest ret;
ret.empty_ = empty_ && values.empty();
return ret;
}
bool empty() const { return empty_; }
private:
bool empty_ = true;
};
extern "C" FOLLY_KEEP void check_folly_digest_builder_append(
DigestBuilder<FreeDigest>& builder, double value) {
builder.append(value);
}
unsigned int append(unsigned int iters, size_t bufSize, size_t nThreads) {
iters = 1000000;
auto buffer = std::make_shared<DigestBuilder<FreeDigest>>(bufSize, 100);
auto barrier = std::make_shared<boost::barrier>(nThreads + 1);
std::vector<std::thread> threads;
threads.reserve(nThreads);
BENCHMARK_SUSPEND {
for (size_t i = 0; i < nThreads; ++i) {
threads.emplace_back([&]() {
barrier->wait();
for (size_t iter = 0; iter < iters; ++iter) {
buffer->append(iter);
}
barrier->wait();
});
}
barrier->wait();
}
barrier->wait();
BENCHMARK_SUSPEND {
for (auto& thread : threads) {
thread.join();
}
}
return iters;
}
BENCHMARK_NAMED_PARAM_MULTI(append, 1000x1, 1000, 1)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 1000x2, 1000, 2)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 1000x4, 1000, 4)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 1000x8, 1000, 8)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 1000x16, 1000, 16)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 1000x32, 1000, 32)
BENCHMARK_DRAW_LINE();
BENCHMARK_NAMED_PARAM_MULTI(append, 10000x1, 10000, 1)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 10000x2, 10000, 2)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 10000x4, 10000, 4)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 10000x8, 10000, 8)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 10000x16, 10000, 16)
BENCHMARK_RELATIVE_NAMED_PARAM_MULTI(append, 10000x32, 10000, 32)
/*
* ./digest_buffer_benchmark
* ============================================================================
* folly/stats/test/DigestBuilderBenchmark.cpp relative time/iter iters/s
* ============================================================================
* append(1000x1) 16.32ns 61.26M
* append(1000x2) 96.42% 16.93ns 59.07M
* append(1000x4) 93.57% 17.44ns 57.33M
* append(1000x8) 93.43% 17.47ns 57.24M
* append(1000x16) 92.96% 17.56ns 56.95M
* append(1000x32) 29.23% 55.84ns 17.91M
* ----------------------------------------------------------------------------
* append(10000x1) 11.58ns 86.33M
* append(10000x2) 95.82% 12.09ns 82.72M
* append(10000x4) 89.00% 13.01ns 76.84M
* append(10000x8) 88.63% 13.07ns 76.51M
* append(10000x16) 88.22% 13.13ns 76.16M
* append(10000x32) 24.89% 46.54ns 21.49M
* ============================================================================
*/
int main(int argc, char* argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
folly::runBenchmarks();
return 0;
}