cachelib/allocator/LruTailAgeStrategy.h (61 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. */ #pragma once #include "cachelib/allocator/RebalanceStrategy.h" namespace facebook { namespace cachelib { // If an allocation class has its tail age higher than a threshold, // we look at how much it is higher than the average tail age. If the // differnece is greater than the tail age difference ratio specified // in the config, that allocation class will release a slab. class LruTailAgeStrategy : public RebalanceStrategy { public: struct Config : public BaseConfig { // any LRU whose tail age surpasses the average tail age by this ratio is to // be rebalanced double tailAgeDifferenceRatio{0.25}; // minimum tail age difference between victim and receiver for a slab // rebalance to happen unsigned int minTailAgeDifference{100}; // minimum number of slabs to retain in every allocation class. unsigned int minSlabs{1}; // use free memory if it is amounts to more than this many slabs. unsigned int numSlabsFreeMem{3}; // how many slabs worth of items do we project to determine a victim. unsigned int slabProjectionLength{1}; // Weight function can be changed as config parameter. By default, // weight function is null, and no weighted tail age is computed. // If the weight function is set, tailAgeDifferenceRatio and // minTailAgeDifference are ignored using WeightFn = std::function<double( const PoolId pid, const ClassId classId, const PoolStats& pStats)>; WeightFn getWeight = {}; // The free memory threshold to be used to pick victim class. size_t getFreeMemThreshold() const noexcept { return numSlabsFreeMem * Slab::kSize; } Config() noexcept {} Config(double ratio, unsigned int _minSlabs) noexcept : tailAgeDifferenceRatio(ratio), minSlabs{_minSlabs} {} Config(double ratio, unsigned int _minSlabs, const WeightFn& _getWeight) noexcept : tailAgeDifferenceRatio(ratio), minSlabs{_minSlabs}, getWeight(_getWeight) {} }; // Update the config. This will not affect the current rebalancing, but // will take effect in the next round void updateConfig(const BaseConfig& baseConfig) override { std::lock_guard<std::mutex> l(configLock_); config_ = static_cast<const Config&>(baseConfig); } explicit LruTailAgeStrategy(Config config = {}); protected: // This returns a copy of the current config. // This ensures that we're always looking at the same config even though // someone else may have updated the config during rebalancing Config getConfigCopy() const { std::lock_guard<std::mutex> l(configLock_); return config_; } RebalanceContext pickVictimAndReceiverImpl(const CacheBase& cache, PoolId pid) override final; ClassId pickVictimImpl(const CacheBase& cache, PoolId pid) override final; private: static AllocInfo makeAllocInfo(PoolId pid, ClassId cid, const PoolStats& stats) { return AllocInfo{pid, cid, stats.allocSizeForClass(cid)}; } ClassId pickVictim(const Config& config, PoolId pid, const PoolStats& stats, const PoolEvictionAgeStats& poolEvictionAgeStats); ClassId pickReceiver(const Config& config, PoolId pid, const PoolStats& stats, ClassId victim, const PoolEvictionAgeStats& poolEvictionAgeStats) const; // Config for this strategy, this can be updated anytime. // Do not access this directly, always use `getConfig()` to // obtain a copy first Config config_; mutable std::mutex configLock_; }; } // namespace cachelib } // namespace facebook