// all the pieces concatenated into one message.
//
void Final(
- uint64_t *hash1, // out only: first 64 bits of hash value.
- uint64_t *hash2); // out only: second 64 bits of hash value.
+ uint64_t *hash1, // out only: first 64 bits of hash value.
+ uint64_t *hash2) const; // out only: second 64 bits of hash value.
//
// left rotate a 64-bit value by k bytes
uint64_t *hash2); // in/out: in the seed, out the hash value
// number of uint64_t's in internal state
- static const size_t sc_numVars = 12;
+ static constexpr size_t sc_numVars = 12;
// size of the internal state
- static const size_t sc_blockSize = sc_numVars*8;
+ static constexpr size_t sc_blockSize = sc_numVars*8;
// size of buffer of unhashed data, in bytes
- static const size_t sc_bufSize = 2*sc_blockSize;
+ static constexpr size_t sc_bufSize = 2*sc_blockSize;
//
// sc_const: a constant which:
// * is a not-very-regular mix of 1's and 0's
// * does not need any other special mathematical properties
//
- static const uint64_t sc_const = 0xdeadbeefdeadbeefLL;
+ static constexpr uint64_t sc_const = 0xdeadbeefdeadbeefLL;
uint64_t m_data[2*sc_numVars]; // unhashed data, for partial messages
uint64_t m_state[sc_numVars]; // internal state of the hash
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * 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 <stdint.h>
+
+#include <deque>
+#include <random>
+#include <string>
+#include <vector>
+
+#include <folly/Benchmark.h>
+#include <folly/Format.h>
+#include <folly/Hash.h>
+#include <folly/Preprocessor.h>
+#include <gflags/gflags.h>
+#include <glog/logging.h>
+
+namespace detail {
+
+std::vector<uint8_t> randomBytes(size_t n) {
+ std::vector<uint8_t> ret(n);
+ std::default_random_engine rng(1729); // Deterministic seed.
+ std::uniform_int_distribution<uint8_t> dist(0, 255);
+ std::generate(ret.begin(), ret.end(), [&] () { return dist(rng); });
+ return ret;
+}
+
+std::vector<uint8_t> benchData = randomBytes(1 << 20); // 1MiB, fits in cache.
+
+template <class Hasher>
+void bmHasher(Hasher hasher, size_t k, size_t iters) {
+ CHECK_LE(k, benchData.size());
+ for (size_t i = 0, pos = 0; i < iters; ++i, ++pos) {
+ if (pos == benchData.size() - k + 1) { pos = 0; }
+ folly::doNotOptimizeAway(hasher(benchData.data() + pos, k));
+ }
+}
+
+template <class Hasher>
+void addHashBenchmark(const std::string& name) {
+ static std::deque<std::string> names;
+
+ for (size_t i = 0; i < 16; ++i) {
+ size_t k = 1 << i;
+ names.emplace_back(folly::sformat("{}: k=2^{}",name, i));
+ folly::addBenchmark(__FILE__, names.back().c_str(),
+ [=] (unsigned iters) {
+ Hasher hasher;
+ bmHasher(hasher, k, iters);
+ return iters;
+ });
+ }
+
+ /* Draw line. */
+ folly::addBenchmark(__FILE__, "-", [] () { return 0; });
+}
+
+struct SpookyHashV2 {
+ uint64_t operator()(const uint8_t* data, size_t size) const {
+ return folly::hash::SpookyHashV2::Hash64(data, size, 0);
+ }
+};
+
+struct FNV64 {
+ uint64_t operator()(const uint8_t* data, size_t size) const {
+ return folly::hash::fnv64_buf(data, size);
+ }
+};
+
+}
+
+int main(int argc, char** argv) {
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
+ google::InitGoogleLogging(argv[0]);
+
+ std::deque<std::string> names; // Backing for benchmark names.
+
+#define BENCHMARK_HASH(HASHER) \
+ detail::addHashBenchmark<detail::HASHER>(FB_STRINGIZE(HASHER));
+
+ BENCHMARK_HASH(SpookyHashV2);
+ BENCHMARK_HASH(FNV64);
+
+#undef BENCHMARK_HASH
+
+ folly::runBenchmarks();
+
+ return 0;
+}
+
+#if 0
+Intel(R) Xeon(R) CPU E5-2660 0 @ 2.20GHz
+$ hash_benchmark --bm_min_usec=100000
+============================================================================
+folly/test/HashBenchmark.cpp relative time/iter iters/s
+============================================================================
+SpookyHashV2: k=2^0 11.67ns 85.66M
+SpookyHashV2: k=2^1 12.49ns 80.07M
+SpookyHashV2: k=2^2 11.87ns 84.22M
+SpookyHashV2: k=2^3 12.36ns 80.89M
+SpookyHashV2: k=2^4 21.47ns 46.58M
+SpookyHashV2: k=2^5 22.21ns 45.02M
+SpookyHashV2: k=2^6 31.47ns 31.78M
+SpookyHashV2: k=2^7 49.86ns 20.05M
+SpookyHashV2: k=2^8 69.56ns 14.38M
+SpookyHashV2: k=2^9 102.99ns 9.71M
+SpookyHashV2: k=2^10 153.72ns 6.51M
+SpookyHashV2: k=2^11 271.43ns 3.68M
+SpookyHashV2: k=2^12 498.85ns 2.00M
+SpookyHashV2: k=2^13 961.55ns 1.04M
+SpookyHashV2: k=2^14 1.88us 532.57K
+SpookyHashV2: k=2^15 3.73us 268.42K
+--------------------------------------------------------------------------
+FNV64: k=2^0 2.67ns 374.83M
+FNV64: k=2^1 4.67ns 214.24M
+FNV64: k=2^2 10.30ns 97.07M
+FNV64: k=2^3 23.16ns 43.17M
+FNV64: k=2^4 48.77ns 20.51M
+FNV64: k=2^5 100.45ns 9.96M
+FNV64: k=2^6 201.74ns 4.96M
+FNV64: k=2^7 399.42ns 2.50M
+FNV64: k=2^8 801.64ns 1.25M
+FNV64: k=2^9 1.59us 627.32K
+FNV64: k=2^10 3.19us 313.51K
+FNV64: k=2^11 6.38us 156.80K
+FNV64: k=2^12 12.75us 78.45K
+FNV64: k=2^13 25.49us 39.23K
+FNV64: k=2^14 50.98us 19.62K
+FNV64: k=2^15 101.93us 9.81K
+----------------------------------------------------------------------------
+============================================================================
+#endif