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.
18 #include <folly/Benchmark.h>
19 #include <folly/Format.h>
20 #include <folly/detail/SlowFingerprint.h>
21 #include <folly/Fingerprint.h>
24 using namespace folly;
25 using folly::detail::SlowFingerprint;
28 constexpr int kMaxIds = 64 << 10; // 64Ki
29 constexpr int kMaxTerms = 64 << 10;
31 // Globals are generally bad, but this is a benchmark, so there.
32 uint64_t ids[kMaxIds];
34 std::string terms[kMaxTerms];
38 for (int i = 0; i < kMaxIds; i++) {
39 ids[i] = (((uint64_t)rng()) << 32) | rng();
41 // Use randomly generated words. These numbers are out of my hat and
43 // word length = uniformly distributed between 1 and 10
44 // charset = 0x20 - 0x7f
45 std::uniform_int_distribution<size_t> term_len(1, 10);
46 std::uniform_int_distribution<uint16_t> term_char(0x20, 0x7f);
47 for (int i = 0; i < kMaxTerms; i++) {
48 std::string& term = terms[i];
49 int len = term_len(rng);
51 for (int j = 0; j < len; j++) {
52 term.append(1, (char)term_char(rng));
58 void fingerprintIds(int num_iterations, int num_ids) {
59 for (int iter = 0; iter < num_iterations; iter++) {
61 for (int i = 0; i < num_ids; i++) {
64 // GOTCHA: if we don't actually call write(), compiler optimizes
65 // away the inner loop!
73 void fingerprintTerms(int num_iterations, int num_terms) {
74 for (int iter = 0; iter < num_iterations; iter++) {
76 for (int i = 0; i < num_terms; i++) {
79 // GOTCHA: if we don't actually call write(), compiler optimizes
80 // away the inner loop!
87 void fastFingerprintIds64(int num_iterations, int num_ids) {
88 fingerprintIds<Fingerprint<64> >(num_iterations, num_ids);
91 void slowFingerprintIds64(int num_iterations, int num_ids) {
92 fingerprintIds<SlowFingerprint<64> >(num_iterations, num_ids);
95 void fastFingerprintIds96(int num_iterations, int num_ids) {
96 fingerprintIds<Fingerprint<96> >(num_iterations, num_ids);
99 void fastFingerprintIds128(int num_iterations, int num_ids) {
100 fingerprintIds<Fingerprint<128> >(num_iterations, num_ids);
103 void fastFingerprintTerms64(int num_iterations, int num_ids) {
104 fingerprintTerms<Fingerprint<64> >(num_iterations, num_ids);
107 void slowFingerprintTerms64(int num_iterations, int num_ids) {
108 fingerprintTerms<SlowFingerprint<64> >(num_iterations, num_ids);
111 void fastFingerprintTerms96(int num_iterations, int num_ids) {
112 fingerprintTerms<Fingerprint<96> >(num_iterations, num_ids);
115 void fastFingerprintTerms128(int num_iterations, int num_ids) {
116 fingerprintTerms<Fingerprint<128> >(num_iterations, num_ids);
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.
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) { \
132 sformat("{}_{}", #name, i).c_str(), \
133 [=](int iters) { name(iters, i); return iters; }); \
135 BM(fastFingerprintIds64, 1, kMaxIds)
136 BM(slowFingerprintIds64, 1, kMaxIds)
137 BM(fastFingerprintIds96, 1, kMaxIds)
138 BM(fastFingerprintIds128, 1, kMaxIds)
139 BM(fastFingerprintTerms64, 1, kMaxTerms)
140 BM(slowFingerprintTerms64, 1, kMaxTerms)
141 BM(fastFingerprintTerms96, 1, kMaxTerms)
142 BM(fastFingerprintTerms128, 1, kMaxTerms)