proxygen
FingerprintBenchmark.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-present Facebook, Inc.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 #include <random>
18 
19 #include <folly/Benchmark.h>
20 #include <folly/Fingerprint.h>
21 #include <folly/Format.h>
23 
24 using namespace std;
25 using namespace folly;
27 
28 namespace {
29 constexpr int kMaxIds = 64 << 10; // 64Ki
30 constexpr int kMaxTerms = 64 << 10;
31 
32 // Globals are generally bad, but this is a benchmark, so there.
33 uint64_t ids[kMaxIds];
34 
35 std::string terms[kMaxTerms];
36 
37 void initialize() {
38  std::mt19937 rng;
39  for (int i = 0; i < kMaxIds; i++) {
40  ids[i] = (((uint64_t)rng()) << 32) | rng();
41  }
42  // Use randomly generated words. These numbers are out of my hat and
43  // probably wrong.
44  // word length = uniformly distributed between 1 and 10
45  // charset = 0x20 - 0x7f
46  std::uniform_int_distribution<size_t> term_len(1, 10);
47  std::uniform_int_distribution<uint16_t> term_char(0x20, 0x7f);
48  for (int i = 0; i < kMaxTerms; i++) {
49  std::string& term = terms[i];
50  int len = term_len(rng);
51  term.reserve(len);
52  for (int j = 0; j < len; j++) {
53  term.append(1, (char)term_char(rng));
54  }
55  }
56 }
57 
58 template <class FP>
59 void fingerprintIds(int num_iterations, int num_ids) {
60  for (int iter = 0; iter < num_iterations; iter++) {
61  FP fp;
62  for (int i = 0; i < num_ids; i++) {
63  fp.update64(ids[i]);
64  }
65  // GOTCHA: if we don't actually call write(), compiler optimizes
66  // away the inner loop!
67  uint64_t out;
68  fp.write(&out);
69  VLOG(1) << out;
70  }
71 }
72 
73 template <class FP>
74 void fingerprintTerms(int num_iterations, int num_terms) {
75  for (int iter = 0; iter < num_iterations; iter++) {
76  FP fp;
77  for (int i = 0; i < num_terms; i++) {
78  fp.update(terms[i]);
79  }
80  // GOTCHA: if we don't actually call write(), compiler optimizes
81  // away the inner loop!
82  uint64_t out;
83  fp.write(&out);
84  VLOG(1) << out;
85  }
86 }
87 
88 void fastFingerprintIds64(int num_iterations, int num_ids) {
89  fingerprintIds<Fingerprint<64>>(num_iterations, num_ids);
90 }
91 
92 void slowFingerprintIds64(int num_iterations, int num_ids) {
93  fingerprintIds<SlowFingerprint<64>>(num_iterations, num_ids);
94 }
95 
96 void fastFingerprintIds96(int num_iterations, int num_ids) {
97  fingerprintIds<Fingerprint<96>>(num_iterations, num_ids);
98 }
99 
100 void fastFingerprintIds128(int num_iterations, int num_ids) {
101  fingerprintIds<Fingerprint<128>>(num_iterations, num_ids);
102 }
103 
104 void fastFingerprintTerms64(int num_iterations, int num_ids) {
105  fingerprintTerms<Fingerprint<64>>(num_iterations, num_ids);
106 }
107 
108 void slowFingerprintTerms64(int num_iterations, int num_ids) {
109  fingerprintTerms<SlowFingerprint<64>>(num_iterations, num_ids);
110 }
111 
112 void fastFingerprintTerms96(int num_iterations, int num_ids) {
113  fingerprintTerms<Fingerprint<96>>(num_iterations, num_ids);
114 }
115 
116 void fastFingerprintTerms128(int num_iterations, int num_ids) {
117  fingerprintTerms<Fingerprint<128>>(num_iterations, num_ids);
118 }
119 
120 } // namespace
121 
122 // Only benchmark one size of slowFingerprint; it's significantly slower
123 // than fastFingeprint (as you can see for 64 bits) and it just slows down
124 // the benchmark without providing any useful data.
125 
126 int main(int argc, char** argv) {
127  gflags::ParseCommandLineFlags(&argc, &argv, true);
128 #define BM(name, min, max) \
129  for (size_t i = min; i <= max; i *= 2) { \
130  addBenchmark( \
131  __FILE__, sformat("{}_{}", #name, i).c_str(), [=](int iters) { \
132  name(iters, i); \
133  return iters; \
134  }); \
135  }
136  BM(fastFingerprintIds64, 1, kMaxIds)
137  BM(slowFingerprintIds64, 1, kMaxIds)
138  BM(fastFingerprintIds96, 1, kMaxIds)
139  BM(fastFingerprintIds128, 1, kMaxIds)
140  BM(fastFingerprintTerms64, 1, kMaxTerms)
141  BM(slowFingerprintTerms64, 1, kMaxTerms)
142  BM(fastFingerprintTerms96, 1, kMaxTerms)
143  BM(fastFingerprintTerms128, 1, kMaxTerms)
144 #undef BM
145 
146  initialize();
147  runBenchmarks();
148  return 0;
149 }
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void runBenchmarks()
Definition: Benchmark.cpp:456
#define BM(name, min, max)
auto rng
Definition: CollectTest.cpp:31
char ** argv
const char * string
Definition: Conv.cpp:212
int main(int argc, char **argv)