本地AI模型实现LRU 及其比较

gemma2(9.2b)

js 复制代码
class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
  }

  get(key) {
    if (this.cache.has(key)) {
      const value = this.cache.get(key);
      this.moveToFront(key); // 将访问过的 key 移到最前面
      return value;
    }
    return -1; // 键不存在
  }

  put(key, value) {
    if (this.cache.has(key)) {
      this.cache.set(key, value);
      this.moveToFront(key); // 更新值后,将 key 移到最前面
    } else {
      if (this.cache.size >= this.capacity) {
        // 缓存已满,移除最不经常使用的项
        const oldestKey = this.getOldestKey();
        this.cache.delete(oldestKey);
      }
      this.cache.set(key, value);
    }
  }

  moveToFront(key) {
    // 将 key 移到最前面
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value);
  }

  getOldestKey() {
    // 返回最不经常使用的 key
    return Array.from(this.cache.keys())[0];
  }
}

// 示例用法
const cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1)); // 返回 1
cache.put(3, 3); // 移除 key 2
console.log(cache.get(2)); // 返回 -1
cache.put(4, 4); // 移除 key 1
console.log(cache.get(1)); // 返回 -1
console.log(cache.get(3)); // 返回 3
console.log(cache.get(4)); // 返回 4
kotlin 复制代码
class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
  }

  get(key) {
    if (this.cache.has(key)) {
      const value = this.cache.get(key);
      this.moveToFront(key); // 将访问过的 key 移到最前面
      return value;
    }
    return -1; // 键不存在
  }

  put(key, value) {
    if (this.cache.has(key)) {
      this.cache.set(key, value);
      this.moveToFront(key); // 更新值后,将 key 移到最前面
    } else {
      if (this.cache.size >= this.capacity) {
        // 缓存已满,移除最不经常使用的项
        const oldestKey = this.getOldestKey();
        this.cache.delete(oldestKey);
      }
      this.cache.set(key, value);
    }
  }

  moveToFront(key) {
    // 将 key 移到最前面
    const value = this.cache.get(key);
    this.cache.delete(key);
    this.cache.set(key, value);
  }

  getOldestKey() {
    // 返回最不经常使用的 key
    return Array.from(this.cache.keys())[0];
  }
}

// 示例用法
const cache = new LRUCache(2);
cache.put(1, 1);
cache.put(2, 2);
console.log(cache.get(1)); // 返回 1
cache.put(3, 3); // 移除 key 2
console.log(cache.get(2)); // 返回 -1
cache.put(4, 4); // 移除 key 1
console.log(cache.get(1)); // 返回 -1
console.log(cache.get(3)); // 返回 3
console.log(cache.get(4)); // 返回 4

解释:

  • LRUCache 类实现了一个容量为 capacity 的LRU 缓存。

  • cache 是一个 Map,用于存储键值对。

  • get(key) 方法:

    • 检查 key 是否存在于 cache 中。
    • 如果存在,则返回对应的值,并使用 moveToFront(key)key 移到最前面。
    • 如果不存在,则返回 -1
  • put(key, value) 方法:

    • 如果 key 已经存在,则更新对应的值并使用 moveToFront(key)key 移到最前面。

    • 如果 key 不存在:

      • 如果 cache 已满,则使用 getOldestKey() 获取最不经常使用的 key 并从 cache 中删除。
      • 将新的 keyvalue 添加到 cache 中。
  • moveToFront(key) 方法:

    • cache 中删除 key,然后将其重新添加到最前面。
  • getOldestKey() 方法:

    • 返回 cache 中的第一个键(即最不经常使用的键)。

phi3(3.8b)

js 复制代码
function LRUCache(capacity) {
  this.cache = []; // 存储元素的列表
  this.cacheMap = new Map(); // 存储元素及其索引关系
  this.capacity = capacity;
}

LRUCache.prototype.get = function(key) {
  if (this.cacheMap.has(key)) {
    let index = this.cacheMap.get(key);
    // 将该元素前移
    this.moveToFront(index);
    return this.cache[index];
  }
  return -1; // 返回-1表示不存在
};

LRUCache.prototype.put = function(key, value) {
  if (this.cacheMap.has(key)) {
    // 如果键已经在缓存中,则前移它到首位
    let index = this.cacheMap.get(key);
    this.moveToFront(index);
    this.cache[index] = value;
  } else {
    // 添加新元素
    if (this.cache.length >= this.capacity) {
      let leastRecentlyUsedKey = this.popLeastUsed();
      delete this.cacheMap.get(leastRecentlyUsedKey);
    }
    this.addToFront(key, value);
  }
};

LRUCache.prototype.remove = function(key) {
  if (this.cacheMap.has(key)) {
    let index = this.cacheMap.get(key);
    this.cache[index] = undefined; // 弹出元素值为undefined
    this.cacheMap.delete(key); // 从索引-值对象中删除
    if (this.cache.length < Math.ceil(this.capacity / 2)) {
      // 如果缓存容量低于一半的大小,则合并尾部元素与首部元素
      let lastIndex = this.cache.pop();
      if (lastIndex !== undefined) {
        delete this.cacheMap.get(this.cache[0]); // 删除首部元素对应索引-值对象中的关系
        this.addToFront(this.cache[lastIndex], this.cacheMap.keys().next().value);
      }
    }
  }
};

LRUCache.prototype.popLeastUsed = function() {
  if (this.cache.length === 0) return undefined; // 缓存为空时返回undefined
  let lastIndex = this.cache.length - 1;
  let leastRecentlyUsedKey = this.cache[lastIndex];
  delete this.cacheMap.get(leastRecentlyUsedKey);
  return leastRecentlyUsedKey; // 返回释放元素的索引
};

LRUCache.prototype.addToFront = function(key, value) {
  if (this.cache.length >= this.capacity) throw new Error('Capacity exceeded');
  this.cache.unshift(value); // 前移元素到首位
  let index = this.cache.length - 1;
  this.cacheMap.set(key, index); // 更新索引-值对象中关系
};

LRUCache.prototype.moveToFront = function(index) {
  if (this.cache.length <= index) throw new Error('Index out of range');
  let key = this.cache[index];
  this.remove(key); // 先移除以后再前移
  this.addToFront(key, this.cache[index]);
};

这个LRUCache类的主要方法包括:

  • get(key): 返回值对应于指定键的元素。如果没有查询到,则返回-1。
  • put(key, value): 将键值对存入缓存中,并根据最近使用到的规则移动元素。如果超过了容量限制,需要移除LRU(Least Recently Used)元素。
  • remove(key): 移除指定键对应的元素。

这个实现是简单且可以理解的,但在大规模或高性能场景下,可能需要更进一步的优化和改进。

llama3(8.0b)

kotlin 复制代码
class LRUCache {
  constructor(capacity) {
    this.capacity = capacity;
    this.cache = new Map();
    this.order = [];
  }

  get(key) {
    if (!this.cache.has(key)) return null;
    const value = this.cache.get(key);
    this.remove(key);
    this.add(key);
    return value;
  }

  set(key, value) {
    if (this.cache.size >= this.capacity) {
      const evictedKey = this.order.shift();
      this.cache.delete(evictiedKey);
    }
    this.cache.set(key, value);
    this.add(key);
  }

  remove(key) {
    if (!this.cache.has(key)) return;
    this.cache.delete(key);
    const index = this.order.indexOf(key);
    if (index !== -1) this.order.splice(index, 1);
  }

  add(key) {
    this.cache.set(key, null); // Update the cache entry
    this.order.push(key);
  }
}

总结

这几个模型生成的代码各有侧重,需根据背景选择使用。

相关推荐
gnip2 小时前
链式调用和延迟执行
前端·javascript
SoaringHeart2 小时前
Flutter组件封装:页面点击事件拦截
前端·flutter
杨天天.2 小时前
小程序原生实现音频播放器,下一首上一首切换,拖动进度条等功能
前端·javascript·小程序·音视频
Dragon Wu3 小时前
React state在setInterval里未获取最新值的问题
前端·javascript·react.js·前端框架
Jinuss3 小时前
Vue3源码reactivity响应式篇之watch实现
前端·vue3
YU大宗师3 小时前
React面试题
前端·javascript·react.js
木兮xg3 小时前
react基础篇
前端·react.js·前端框架
ssshooter3 小时前
你知道怎么用 pnpm 临时给某个库打补丁吗?
前端·面试·npm
IT利刃出鞘4 小时前
HTML--最简的二级菜单页面
前端·html
yume_sibai4 小时前
HTML HTML基础(4)
前端·html