Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a97c3db

Browse files
committedJun 26, 2024·
lfu 设定
1 parent 18cc5d3 commit a97c3db

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed
 

Diff for: ‎README.md

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1-
## algorithm
1+
## algorithm/ 算法结构相关
2+
[![crates.io](https://img.shields.io/crates/v/algorithm.svg)](https://crates.io/crates/algorithm)
3+
[![rustc 1.70.0](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://img.shields.io/badge/rust-1.70%2B-orange.svg)
4+
[![Released API docs](https://docs.rs/algorithm/badge.svg)](https://docs.rs/algorithm)
5+
26
将提供一些常用的数据结构以供使用。目前提供的数据结构
3-
* **LruCache** 最近未使用缓存
4-
* **LruKCache** 最近未使用缓存, K次分类列表
5-
* **LfuCache** 按缓存访问次数做排序,优先淘汰访问最少次数的
7+
* **LruCache** 最近未使用缓存,可用feature启用ttl
8+
* **LruKCache** 最近未使用缓存, K次分类列表,可用feature启用ttl
9+
* **LfuCache** 按缓存访问次数做排序,优先淘汰访问最少次数的,可用feature启用ttl
10+
* **ArcCache** Adaptive Replacement Cache,自适应缓存替换算法,可用feature启用ttl
611
* **Slab** 仿linux中的Slab结构,对大对象做到初始化缓存使用
712
* **BitMap** 位图, 按位做标记的图
813
* **RoaringBitMap** 位图, 因为位图占用的内存太大, 对于稀疏位图会更小内存
914
* **TimerWheel** 计时器轮, 模仿时钟的高效定时器组件
1015
* **CircularBuffer** 环形Buffer组件, 适用于内存限定较严格的, 设置不超过缓存值的环形结构
1116
* **RBTree** 红黑村, 高效的排序树, 可用于做定时器组件
17+
* **FixedVec** 模拟指针的可变长数组
1218

1319
# lru 全称是Least Recently Used,即最近最久未使用的意思。
1420
每次元素访问将其更新到列表的最前,时间复杂度为O(1)。当达到容量限制时将淘汰双向列表中的链尾数据
@@ -201,4 +207,9 @@ fn main() {
201207

202208
assert!(timer.is_empty());
203209
}
204-
```
210+
```
211+
212+
213+
## Star History
214+
215+
[![Star History Chart](https://api.star-history.com/svg?repos=tickbh/algorithm-rs&type=Date)](https://star-history.com/#tickbh/algorithm-rs&Date)

Diff for: ‎src/cache/lfu.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ use crate::get_milltimestamp;
7676
#[cfg(feature = "ttl")]
7777
const DEFAULT_CHECK_STEP: u64 = 120;
7878

79+
/// Lfu节点数据
7980
pub(crate) struct LfuEntry<K, V> {
8081
pub key: mem::MaybeUninit<K>,
8182
pub val: mem::MaybeUninit<V>,
83+
/// 访问总频次
8284
pub counter: usize,
8385
/// 带ttl的过期时间,单位秒
8486
/// 如果为u64::MAX,则表示不过期
@@ -156,11 +158,15 @@ pub struct LfuCache<K, V, S> {
156158
/// 因为HashSet的pop耗时太长, 所以取LfuCache暂时做为平替
157159
times_map: HashMap<u8, LruCache<KeyRef<K>, (), DefaultHasher>>,
158160
cap: usize,
161+
/// 最大的访问频次
159162
max_freq: u8,
163+
/// 最小的访问频次
160164
min_freq: u8,
165+
/// 总的访问次数
161166
visit_count: usize,
162-
167+
/// 初始的访问次数
163168
default_count: usize,
169+
/// 每多少次访问进行一次衰减
164170
reduce_count: usize,
165171

166172
/// 下一次检查的时间点,如果大于该时间点则全部检查是否过期
@@ -552,7 +558,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
552558
if val.is_empty() {
553559
continue;
554560
}
555-
let key = Self::_pop_one(val).unwrap();
561+
let key = val.pop_unusual().unwrap().0;
556562
let value = self.map.remove(&key).expect("must ok");
557563
let node = *Box::from_raw(value.as_ptr());
558564
let LfuEntry { key, val, .. } = node;
@@ -587,7 +593,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
587593
if val.is_empty() {
588594
continue;
589595
}
590-
let key = Self::_pop_one(val).unwrap();
596+
let key = val.pop_unusual().unwrap().0;
591597
let value = self.map.remove(&key).expect("must ok");
592598
let node = *Box::from_raw(value.as_ptr());
593599
let LfuEntry { key, val, .. } = node;
@@ -1061,7 +1067,7 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
10611067
if val.is_empty() {
10621068
continue;
10631069
}
1064-
let key = Self::_pop_one(val).unwrap();
1070+
let key = val.pop_unusual().unwrap().0;
10651071
let old_node = self.map.remove(&key).unwrap();
10661072
let node_ptr: *mut LfuEntry<K, V> = old_node.as_ptr();
10671073

@@ -1123,16 +1129,16 @@ impl<K: Hash + Eq, V, S: BuildHasher> LfuCache<K, V, S> {
11231129
}
11241130
}
11251131

1126-
fn _pop_one(keys: &mut LruCache<KeyRef<K>, (), DefaultHasher>) -> Option<KeyRef<K>> {
1127-
keys.pop_usual().map(|(k, _)| k)
1128-
// let k = if let Some(k) = keys.iter().next() {
1129-
// KeyRef { k: k.k }
1130-
// } else {
1131-
// return None;
1132-
// };
1133-
// keys.remove(&k);
1134-
// Some(k)
1135-
}
1132+
// fn _pop_one(keys: &mut LruCache<KeyRef<K>, (), DefaultHasher>) -> Option<KeyRef<K>> {
1133+
// keys.pop_usual().map(|(k, _)| k)
1134+
// // let k = if let Some(k) = keys.iter().next() {
1135+
// // KeyRef { k: k.k }
1136+
// // } else {
1137+
// // return None;
1138+
// // };
1139+
// // keys.remove(&k);
1140+
// // Some(k)
1141+
// }
11361142
}
11371143

11381144

0 commit comments

Comments
 (0)
Please sign in to comment.