cachelib/common/hothash/HotHashDetectorTest.cpp (65 lines of code) (raw):
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 <folly/Random.h>
#include <gtest/gtest.h>
#include <cstdlib>
#include <random>
#include "cachelib/common/hothash/HotHashDetector.h"
using facebook::cachelib::HotHashDetector;
static void testHotHashes(uint32_t seed,
size_t numBuckets,
size_t numOfWarmItems,
size_t hotnessMultiplier,
size_t numHashes,
size_t numHotHashes,
uint32_t hotHashProbabilityMultiplier,
size_t batchSize,
size_t maxIterations) {
std::mt19937 prng(seed);
unsigned attempts = 0;
static constexpr unsigned MAX_ATTEMPTS = 1; // Can relax if needed
while (attempts < MAX_ATTEMPTS) {
HotHashDetector detector(numBuckets, numOfWarmItems, hotnessMultiplier);
std::vector<uint64_t> hashes(
numHashes + numHotHashes * (hotHashProbabilityMultiplier - 1));
for (size_t i = 0; i < numHashes; ++i) {
hashes[i] = folly::Random::rand64(prng);
}
for (size_t i = 0; i < numHotHashes; ++i) {
for (size_t j = 0; j < hotHashProbabilityMultiplier - 1; ++j) {
hashes[numHashes + j * numHotHashes + i] = hashes[i];
}
}
size_t iteration = 0;
size_t hotCount = 0;
while (hotCount != numHotHashes && iteration < maxIterations) {
for (size_t i = 0; i + numHashes < batchSize; ++i) {
uint32_t chosenIdx = folly::Random::rand32(0, hashes.size(), prng);
detector.bumpHash(hashes[chosenIdx]);
}
hotCount = 0;
for (size_t i = 0; i < numHashes; ++i) {
hotCount += detector.bumpHash(hashes[i]) ? 1 : 0;
}
++iteration;
}
ASSERT_NE(maxIterations, iteration);
size_t errorCount = 0;
uint32_t hotnessSum = 0;
for (size_t i = 0; i < numHotHashes; ++i) {
uint8_t hotness = detector.bumpHash(hashes[i]);
errorCount += hotness ? 0 : 1;
hotnessSum += hotness;
}
if (errorCount == 0) { // Can relax if needed
ASSERT_LE(hotnessSum, numHotHashes * 2);
break;
}
++attempts;
}
ASSERT_NE(attempts, MAX_ATTEMPTS);
}
TEST(HotHashDetectorTest, Basic) {
for (uint32_t seed = 1000; seed < 1020; ++seed) {
// Passing parameters to testHotHashes:
// seed, numBuckets, numOfWarmItems, hotnessMultiplier, numHashes,
// numHotHashes, hotHashProbabilityMultiplier, batchSize, maxIterations
testHotHashes(seed, 32, 8, 4, 100, 4, 50, 4000, 30);
testHotHashes(seed, 128, 8, 6, 200, 5, 30, 12000, 50);
}
}