diff --git a/folly/container/EvictingCacheMap.h b/folly/container/EvictingCacheMap.h index 7d5f85a7a1df3b88efff8ecfb61b2b0ebee46f9f..e6773d6b6f2269a44bdf97ec7b9adde501d91034 100644 --- a/folly/container/EvictingCacheMap.h +++ b/folly/container/EvictingCacheMap.h @@ -256,8 +256,7 @@ class EvictingCacheMap { if (it == index_.end()) { return end(); } - lru_.erase(lru_.iterator_to(*it)); - lru_.push_front(*it); + lru_.splice(lru_.begin(), lru_, lru_.iterator_to(*it)); return iterator(lru_.iterator_to(*it)); } @@ -343,8 +342,7 @@ class EvictingCacheMap { if (it != index_.end()) { it->pr.second = std::move(value); if (promote) { - lru_.erase(lru_.iterator_to(*it)); - lru_.push_front(*it); + lru_.splice(lru_.begin(), lru_, lru_.iterator_to(*it)); } } else { auto node = new Node(key, std::move(value)); diff --git a/folly/container/test/EvictingCacheMapBench.cpp b/folly/container/test/EvictingCacheMapBench.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c50656a7460bcf784cf6a0b28a5409cc8992799c --- /dev/null +++ b/folly/container/test/EvictingCacheMapBench.cpp @@ -0,0 +1,51 @@ +/* + * 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/container/EvictingCacheMap.h> + +#include <folly/Benchmark.h> + +using namespace folly; + +// This function creates a cache of size `numElts` and scans through it `n` +// times in order to cause the most churn in the LRU structure as possible. +// This is meant to exercise the performance of the lookup path in the cache, +// most notably promotions within the LRU. +void scanCache(uint32_t n, size_t numElts) { + BenchmarkSuspender suspender; + + EvictingCacheMap<size_t, size_t> m(numElts); + for (size_t i = 0; i < numElts; ++i) { + m.insert(i, i); + } + + suspender.dismissing([&]() { + for (uint32_t i = 0; i < n; ++i) { + for (size_t j = 0; j < numElts; ++j) { + m.get(j); + } + } + }); +} + +BENCHMARK_PARAM(scanCache, 1000) // 1K +BENCHMARK_PARAM(scanCache, 10000) // 10K +BENCHMARK_PARAM(scanCache, 100000) // 100K +BENCHMARK_PARAM(scanCache, 1000000) // 1M + +int main() { + runBenchmarks(); +}