本地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);
  }
}

总结

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

相关推荐
MiyueFE6 分钟前
bpmn-js 源码篇7:Featrues 体验优化与功能扩展(二)
前端
好_快21 分钟前
Lodash源码阅读-isPrototype
前端·javascript·源码阅读
315356691336 分钟前
manus邀请码申请手把手教程
前端·后端·面试
烂蜻蜓1 小时前
HTML 编辑器推荐与 VS Code 使用教程
前端·python·编辑器·html
小画家~2 小时前
第五十九:子传父 defineEmits
前端·javascript·vue.js
html组态2 小时前
组态软件在物联网中的应用概述
前端·物联网·编辑器·html·iot
咖啡虫2 小时前
react中的useContext-弊端(二)
前端·javascript·react.js
懒人村杂货铺2 小时前
react精简面试题
前端·react.js·前端框架
青红光硫化黑2 小时前
React基础之tsx语法
前端·javascript·react.js
好_快2 小时前
Lodash源码阅读-isEmpty
前端·javascript·源码阅读