cachelib/allocator/HitsPerSlabStrategy.h (68 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 {
// Strategy that rebalances the slabs by moving slabs from the allocation class
// with the lowest hits per slab to the highest hits per slab within the pool.
class HitsPerSlabStrategy : public RebalanceStrategy {
public:
struct Config : public BaseConfig {
// Absolute difference to be rebalanced
unsigned int minDiff{100};
// Relative difference to be rebalanced
double diffRatio{0.1};
// minimum number of slabs to retain in every allocation class.
unsigned int minSlabs{1};
// use free memory if it amounts to more than this many slabs.
unsigned int numSlabsFreeMem{3};
// minimum tail age for an allocation class to be eligible to be a victim
unsigned int minLruTailAge{0};
// optionial weight function based on allocation class size
using WeightFn = std::function<double(
const PoolId, const ClassId, const PoolStats& pStats)>;
WeightFn getWeight = {};
// free memory threshold used to pick victim.
size_t getFreeMemThreshold() const noexcept {
return numSlabsFreeMem * Slab::kSize;
}
Config() noexcept {}
Config(double ratio, unsigned int _minSlabs) noexcept
: Config(ratio, _minSlabs, 0) {}
Config(double ratio,
unsigned int _minSlabs,
unsigned int _minLruTailAge) noexcept
: diffRatio(ratio),
minSlabs(_minSlabs),
minLruTailAge(_minLruTailAge) {}
Config(double ratio,
unsigned int _minSlabs,
unsigned int _minLruTailAge,
const WeightFn& weightFunction) noexcept
: diffRatio(ratio),
minSlabs(_minSlabs),
minLruTailAge(_minLruTailAge),
getWeight(weightFunction) {}
};
// Update the config. This will not affect the current rebalancing, but
// will take effect in the next round
void updateConfig(const BaseConfig& baseConfig) override final {
std::lock_guard<std::mutex> l(configLock_);
config_ = static_cast<const Config&>(baseConfig);
}
explicit HitsPerSlabStrategy(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,
const CacheBase& cache,
PoolId pid,
const PoolStats& stats);
ClassId pickReceiver(const Config& config,
PoolId pid,
const PoolStats& stats,
ClassId victim) 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