Skip to content

Commit 2cd8e79

Browse files
yfeldblummeta-codesync[bot]
authored andcommitted
benchmark scenario for hazptr_domain::load_hazptr_vals with sqrt(N) protected
Summary: At larger sizes in this scenario, the hprec's are almost completely empty, but not quite. Reviewed By: marksantaniello Differential Revision: D84995170 fbshipit-source-id: 61e3cdf61e10338e6cc698ea1c2160a81fabfef2
1 parent d9cc5b4 commit 2cd8e79

2 files changed

Lines changed: 66 additions & 3 deletions

File tree

folly/synchronization/test/BUCK

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ fbcode_target(
216216
deps = [
217217
"//folly:benchmark",
218218
"//folly/concurrency:atomic_shared_ptr",
219+
"//folly/container:enumerate",
220+
"//folly/container:f14_hash",
219221
"//folly/portability:gflags",
220222
"//folly/synchronization:hazptr",
221223
],

folly/synchronization/test/HazptrBench.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
#include <folly/Benchmark.h>
2424
#include <folly/concurrency/AtomicSharedPtr.h>
25+
#include <folly/container/Enumerate.h>
26+
#include <folly/container/F14Set.h>
2527
#include <folly/portability/GFlags.h>
2628

2729
using namespace folly;
@@ -250,8 +252,8 @@ BENCHMARK_DRAW_LINE();
250252
/// fragment the memory and scatter hprec allocations across cachelines with no
251253
/// consistent stride, if hprecs are allocated separately and linked together
252254
template <template <typename> class Atom>
253-
FOLLY_NOINLINE static void grow_scattered_hprec_list(
254-
hazptr_domain<Atom>& domain, size_t hprec_count) {
255+
FOLLY_NOINLINE static std::vector<hazptr_holder<Atom>>
256+
grow_scattered_hprec_list(hazptr_domain<Atom>& domain, size_t hprec_count) {
255257
using hprec_layout = aligned_storage_for_t<hazptr_rec<std::atomic>>;
256258

257259
std::vector<hazptr_holder<Atom>> holders;
@@ -272,10 +274,13 @@ FOLLY_NOINLINE static void grow_scattered_hprec_list(
272274
/// create hazard pointer, which possibly allocates its hprec
273275
holders.emplace_back(make_hazard_pointer(domain));
274276
}
277+
278+
return holders;
275279
}
276280

277281
/// benchmark hazptr domain cleanup with various hprec-sequence sizes
278-
void hazptr_cleanup_empty_with_hprec_seq(size_t iters, size_t hprec_count) {
282+
static void hazptr_cleanup_empty_with_hprec_seq(
283+
size_t iters, size_t hprec_count) {
279284
BenchmarkSuspender braces;
280285

281286
hazptr_domain<> domain;
@@ -302,6 +307,62 @@ BENCHMARK_PARAM(hazptr_cleanup_empty_with_hprec_seq, 65536)
302307
BENCHMARK_PARAM(hazptr_cleanup_empty_with_hprec_seq, 262144)
303308
BENCHMARK_PARAM(hazptr_cleanup_empty_with_hprec_seq, 1048576)
304309

310+
BENCHMARK_DRAW_LINE();
311+
312+
/// benchmark hazptr domain cleanup with sqrt(N) protected pointers
313+
/// selected uniformly at random from N hprecs
314+
static void hazptr_cleanup_sqrt_with_hprec_seq(
315+
size_t iters, size_t hprec_count) {
316+
BenchmarkSuspender braces;
317+
318+
size_t protected_count = static_cast<size_t>(std::sqrt(hprec_count));
319+
320+
/// create sqrt(N) objects to protect
321+
std::vector<std::unique_ptr<TestObj>> protected_objects;
322+
protected_objects.reserve(protected_count);
323+
for (size_t i = 0; i < protected_count; ++i) {
324+
protected_objects.push_back(std::make_unique<TestObj>(i));
325+
}
326+
327+
/// select sqrt(N) holders uniformly at random to protect objects
328+
std::mt19937_64 rng;
329+
std::uniform_int_distribution<size_t> dist(0, hprec_count - 1);
330+
folly::F14FastSet<size_t> protected_indices;
331+
protected_indices.reserve(protected_count);
332+
while (protected_indices.size() < protected_count) {
333+
protected_indices.insert(dist(rng));
334+
}
335+
336+
hazptr_domain<> domain;
337+
auto holders = grow_scattered_hprec_list(domain, hprec_count);
338+
339+
/// protect the objects using the randomly selected holders
340+
for (auto [objidx, hpidx] : enumerate(protected_indices)) {
341+
std::atomic<TestObj*> ptr{protected_objects[objidx].get()};
342+
holders[hpidx].protect(ptr);
343+
}
344+
345+
braces.dismissing([&] {
346+
while (iters--) {
347+
auto* obj = new TestObj(iters);
348+
obj->retire(domain);
349+
domain.cleanup(); // calls load_hazptr_vals on possibly-scattered hprecs
350+
}
351+
});
352+
}
353+
354+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 1)
355+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 4)
356+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 16)
357+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 64)
358+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 256)
359+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 1024)
360+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 4096)
361+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 16384)
362+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 65536)
363+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 262144)
364+
BENCHMARK_PARAM(hazptr_cleanup_sqrt_with_hprec_seq, 1048576)
365+
305366
int main(int argc, char* argv[]) {
306367
folly::gflags::ParseCommandLineFlags(&argc, &argv, true);
307368
runBenchmarks();

0 commit comments

Comments
 (0)