Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"compilerPath": "C:\\msys64\\mingw64\\bin\\gcc.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-gcc-x64"
}
],
"version": 4
}
2 changes: 1 addition & 1 deletion KArcCache/KArcLfuPart.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ArcLfuPart
if (it != mainCache_.end())
{
updateNodeFrequency(it->second);
value = it->second->getValue();
value = it->second->getValue();//根据key获取value
return true;
}
return false;
Expand Down
24 changes: 13 additions & 11 deletions KLfuCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class FreqList
return head_->next == tail_;
}

// 提那家结点管理方法
// 添加结点管理方法
void addNode(NodePtr node)
{
if (!node || !head_ || !tail_)
Expand Down Expand Up @@ -88,7 +88,7 @@ class KLfuCache : public KICachePolicy<Key, Value>
public:
using Node = typename FreqList<Key, Value>::Node;
using NodePtr = std::shared_ptr<Node>;
using NodeMap = std::unordered_map<Key, NodePtr>;
using NodeMap = std::unordered_map<Key, NodePtr>;//这三行套了个娃

KLfuCache(int capacity, int maxAverageNum = 1000000)
: capacity_(capacity), minFreq_(INT8_MAX), maxAverageNum_(maxAverageNum),
Expand All @@ -106,7 +106,7 @@ class KLfuCache : public KICachePolicy<Key, Value>
auto it = nodeMap_.find(key);
if (it != nodeMap_.end())
{
// 重置其value值
// 重置其value值,因为是put,value可能更新了
it->second->value = value;
// 找到了直接调整就好了,不用再去get中再找一遍,但其实影响不大
getInternal(it->second, value);
Expand All @@ -132,7 +132,7 @@ class KLfuCache : public KICachePolicy<Key, Value>

Value get(Key key) override
{
Value value;
Value value{};//防止出错还是需要初始化
get(key, value);
return value;
}
Expand All @@ -141,7 +141,7 @@ class KLfuCache : public KICachePolicy<Key, Value>
void purge()
{
nodeMap_.clear();
freqToFreqList_.clear();
//freqToFreqList_.clear();
}

private:
Expand All @@ -166,7 +166,8 @@ class KLfuCache : public KICachePolicy<Key, Value>
int curTotalNum_; // 当前访问所有缓存次数总数
std::mutex mutex_; // 互斥锁
NodeMap nodeMap_; // key 到 缓存节点的映射
std::unordered_map<int, FreqList<Key, Value>*> freqToFreqList_;// 访问频次到该频次链表的映射
std::unordered_map<int,std::unique_ptr<FreqList<Key, Value>>> freqToFreqList_;//改成智能指针,方便内存管理
//std::unordered_map<int, FreqList<Key, Value>*> freqToFreqList_;// 访问频次到该频次链表的映射
};

template<typename Key, typename Value>
Expand Down Expand Up @@ -238,7 +239,8 @@ void KLfuCache<Key, Value>::addToFreqList(NodePtr node)
if (freqToFreqList_.find(node->freq) == freqToFreqList_.end())
{
// 不存在则创建
freqToFreqList_[node->freq] = new FreqList<Key, Value>(node->freq);
//改成智能指针就不用new了
freqToFreqList_[node->freq] = std::unique_ptr<FreqList<Key, Value>>(node->freq);
}

freqToFreqList_[freq]->addNode(node);
Expand Down Expand Up @@ -271,7 +273,7 @@ void KLfuCache<Key, Value>::decreaseFreqNum(int num)
}

template<typename Key, typename Value>
void KLfuCache<Key, Value>::handleOverMaxAverageNum()
void KLfuCache<Key, Value>::handleOverMaxAverageNum()//定期给所有频率打折,防止历史包袱
{
if (nodeMap_.empty())
return;
Expand All @@ -290,7 +292,7 @@ void KLfuCache<Key, Value>::handleOverMaxAverageNum()

// 减少频率
node->freq -= maxAverageNum_ / 2;
if (node->freq < 1) node->freq = 1;
if (node->freq < 1) node->freq = 1;//防止freq<1,保证新节点的竞争力

// 添加到新的频率列表
addToFreqList(node);
Expand All @@ -303,10 +305,10 @@ void KLfuCache<Key, Value>::handleOverMaxAverageNum()
template<typename Key, typename Value>
void KLfuCache<Key, Value>::updateMinFreq()
{
minFreq_ = INT8_MAX;
minFreq_ = INT8_MAX;//INT8_MAX太小
for (const auto& pair : freqToFreqList_)
{
if (pair.second && !pair.second->isEmpty())
if (pair.second && !pair.second->isEmpty()) //指针非空且链表非空
{
minFreq_ = std::min(minFreq_, pair.first);
}
Expand Down
27 changes: 15 additions & 12 deletions KLruCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class LruNode
// 提供必要的访问器
Key getKey() const { return key_; }
Value getValue() const { return value_; }
void setValue(const Value& value) { value_ = value; }
void setValue(const Value& value) { value_ = value; }
size_t getAccessCount() const { return accessCount_; }
void incrementAccessCount() { ++accessCount_; }

Expand All @@ -51,7 +51,7 @@ class KLruCache : public KICachePolicy<Key, Value>
using NodeMap = std::unordered_map<Key, NodePtr>;

KLruCache(int capacity)
: capacity_(capacity)
: capacity_(capacity) //将参数 capacity 的值赋给类的成员变量 capacity_
{
initializeList();
}
Expand All @@ -64,7 +64,8 @@ class KLruCache : public KICachePolicy<Key, Value>
if (capacity_ <= 0)
return;

std::lock_guard<std::mutex> lock(mutex_);
std::lock_guard<std::mutex> lock(mutex_); //std::mutex:互斥量(互斥锁),lock_guard:构造时加锁,离开作用域解锁
//std::lock_guard<std::mutex> lock(mutex_);
auto it = nodeMap_.find(key);
if (it != nodeMap_.end())
{
Expand Down Expand Up @@ -113,6 +114,7 @@ class KLruCache : public KICachePolicy<Key, Value>
void initializeList()
{
// 创建首尾虚拟节点
//dummyHead<-最旧<-...<-最新<-dummyTail
dummyHead_ = std::make_shared<LruNodeType>(Key(), Value());
dummyTail_ = std::make_shared<LruNodeType>(Key(), Value());
dummyHead_->next_ = dummyTail_;
Expand All @@ -121,13 +123,13 @@ class KLruCache : public KICachePolicy<Key, Value>

void updateExistingNode(NodePtr node, const Value& value)
{
node->setValue(value);
node->setValue(value); //注意这里的node是指针NodePtr,而不是node实例本身,所以用->
moveToMostRecent(node);
}

void addNewNode(const Key& key, const Value& value)
{
if (nodeMap_.size() >= capacity_)
if (nodeMap_.size() >= capacity_) //缓存空间满则删除最左侧数据
{
evictLeastRecent();
}
Expand All @@ -146,10 +148,10 @@ class KLruCache : public KICachePolicy<Key, Value>

void removeNode(NodePtr node)
{
if(!node->prev_.expired() && node->next_)
if(!node->prev_.expired() && node->next_)
{
auto prev = node->prev_.lock(); // 使用lock()获取shared_ptr
prev->next_ = node->next_;
prev->next_ = node->next_; //prev是上一个结点,node是当前结点,_是当前结点的指针
node->next_->prev_ = prev;
node->next_ = nullptr; // 清空next_指针,彻底断开节点与链表的连接
}
Expand Down Expand Up @@ -266,6 +268,7 @@ class KLruKCache : public KLruCache<Key, Value>
}

private:
//这里的get和put需要加锁,否则多线程同时写historyValueMap_会崩溃
int k_; // 进入缓存队列的评判标准
std::unique_ptr<KLruCache<Key, size_t>> historyList_; // 访问数据历史记录(value为访问次数)
std::unordered_map<Key, Value> historyValueMap_; // 存储未达到k次访问的数据值
Expand All @@ -276,9 +279,9 @@ template<typename Key, typename Value>
class KHashLruCaches
{
public:
KHashLruCaches(size_t capacity, int sliceNum)
KHashLruCaches(size_t capacity, int sliceNum)
: capacity_(capacity)
, sliceNum_(sliceNum > 0 ? sliceNum : std::thread::hardware_concurrency())
, sliceNum_(sliceNum > 0 ? sliceNum : std::thread::hardware_concurrency())//如果用户传了合法的sliceNum就使用,否则默用CPU的核心数
{
size_t sliceSize = std::ceil(capacity / static_cast<double>(sliceNum_)); // 获取每个分片的大小
for (int i = 0; i < sliceNum_; ++i)
Expand All @@ -303,12 +306,12 @@ class KHashLruCaches

Value get(Key key)
{
Value value;
memset(&value, 0, sizeof(value));
Value value{};//值初始化,memset 是按字节清零,会破坏 std::string、vector 等复杂对象的内部结构
//memset(&value, 0, sizeof(value));
get(key, value);
return value;
}

private:
// 将key转换为对应hash值
size_t Hash(Key key)
Expand Down