2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <folly/experimental/flat_combining/test/FlatCombiningExamples.h>
21 #include <folly/Benchmark.h>
22 #include <glog/logging.h>
31 void doWork(int work) {
33 for (int i = work; i > 0; --i) {
36 folly::doNotOptimizeAway(a);
42 typename Mutex = std::mutex,
43 template <typename> class Atom = std::atomic>
55 bool allocAll = false) {
56 using FC = FlatCombining<Example, Mutex, Atom, Req>;
57 using Rec = typename FC::Rec;
59 folly::BenchmarkSuspender susp;
61 std::atomic<bool> start{false};
62 std::atomic<int> started{0};
63 Example ex(lines, dedicated, numRecs);
64 std::atomic<uint64_t> total{0};
68 std::vector<Rec*> v(numRecs);
69 for (int i = 0; i < numRecs; ++i) {
72 for (int i = numRecs; i > 0; --i) {
77 std::vector<std::thread> threads(nthreads);
78 for (int tid = 0; tid < nthreads; ++tid) {
79 threads[tid] = std::thread([&, tid] {
81 Rec* myrec = (combining && tc) ? ex.allocRec() : nullptr;
88 for (int i = tid; i < ops; i += nthreads) {
89 sum += ex.fetchAddNoFC(1);
90 doWork(work); // unrelated work
94 for (int i = tid; i < ops; i += nthreads) {
95 sum += ex.fetchAdd(1, myrec);
96 doWork(work); // unrelated work
100 for (int i = tid; i < ops; i += nthreads) {
102 doWork(work); // unrelated work
107 // test of unstructured exclusive access
108 ex.acquireExclusive();
112 VLOG(2) << tid << " " << ex.getVal() << " ...........";
113 using namespace std::chrono_literals;
114 /* sleep override */ // for coverage
115 std::this_thread::sleep_for(10ms);
116 VLOG(2) << tid << " " << ex.getVal() << " ===========";
120 ex.releaseExclusive();
123 total.fetch_add(sum);
124 if (combining && tc) {
130 while (started.load() < nthreads)
132 auto tbegin = std::chrono::steady_clock::now();
134 // begin time measurement
138 for (auto& t : threads) {
143 // complete any pending asynch ops
147 // end time measurement
148 uint64_t duration = 0;
150 auto tend = std::chrono::steady_clock::now();
151 CHECK_EQ(ops, ex.getVal());
153 uint64_t n = (uint64_t)ops;
154 uint64_t expected = n * (n - 1) / 2;
155 CHECK_EQ(expected, total);
158 std::chrono::duration_cast<std::chrono::nanoseconds>(tend - tbegin)
176 bool allocAll = false) {
177 using M = std::mutex;
179 using Example = FcSimpleExample<M>;
180 return fc_test<Example, bool, M>(
193 using Example = FcCustomExample<Req, M>;
194 return fc_test<Example, Req, M>(
209 } // namespace test {
210 } // namespace folly {