GLM-5.1 在「实现缓存系统」的评测结果

这是该 AI 模型在此测试用例上的详细评测结果。

基本信息

  • 模型名称:GLM-5.1
  • 用例名称:实现缓存系统
  • 测试类型:文本生成
  • 评测维度:代码生成

系统提示词(System Prompt)

这是给 AI 模型的背景设定和角色指令:

你是一名资深后端工程师,擅长数据结构与算法设计,尤其熟悉缓存系统的实现原理。 回答要求: 1. 使用清晰、规范的代码实现,并附上简要的设计思路说明。 2. 必须说明核心操作(get/put)的时间复杂度,并解释如何达到该复杂度。 3. 代码需包含必要的注释,关键逻辑处须有说明。 4. 提供至少 3 个测试用例验证实现的正确性,覆盖边界场景(如容量为 1、缓存满时的淘汰行为)。 5. 编程语言不限,但需保证代码可直接运行。

用户提示词(User Prompt)

这是用户给 AI 模型的具体任务要求:

请实现一个 LRU(最近最少使用)缓存类,具体要求如下: **功能要求:** 1. 初始化时接受一个正整数 `capacity` 作为缓存容量上限。 2. 支持 `get(key)` 操作: - 若 key 存在于缓存中,返回对应的 value,并将该项标记为「最近使用」。 - 若 key 不存在,返回 -1。 3. 支持 `put(key, value)` 操作: - 若 key 已存在,更新其 value,并将该项标记为「最近使用」。 - 若 key 不存在,插入该键值对。 - 若插入后缓存超出容量,则删除**最久未使用**的缓存项,再插入新项。 **性能要求:** - `get` 和 `put` 操作的时间复杂度均须为 **O(1)**。 **示例:**

任务要求

AI 模型需要满足以下要求:

  1. LRU 淘汰逻辑正确:缓存满时淘汰最久未访问的有效条目,get/put 均需更新访问顺序,时间复杂度 O(1)
  2. TTL 过期逻辑正确:惰性删除在 get 时生效,过期条目不计入命中,purge_expired 能正确清理所有过期项
  3. 线程安全实现完整:所有公开方法均持锁操作,无竞态条件,并说明锁类型选择理由
  4. 批量操作语义正确:batch_get 跳过过期/不存在的 key,batch_put 原子性地写入所有条目(持同一把锁)
  5. 统计功能准确:hit_count/miss_count 在 get 和 batch_get 中均正确累计,hit_rate 计算无除零错误,current_size 反映实际有效条目数
  6. 测试用例覆盖关键场景:包含 TTL 过期、LRU 淘汰、并发安全、统计准确性四类验证

评测结果

综合得分

该模型在此用例的得分为:95.0 分(满分 100 分),已通过

基础难度评测结果

  • 得分:95.0 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

你好!作为一名后端工程师,很高兴为你解答这个问题。 LRU(Least Recently Used)缓存是系统设计中最经典的组件之一。在诸如 Redis、Memcached 等主流缓存中间件,以及操作系统的页面置换算法中,都有 LRU 的身影。 下面我将详细说明其设计思路、时间复杂度分析,并提供一段可直接运行的 Python 代码实现及测试用例。 ### 一、 设计思路说明 要实现 `get` 和 `put` 时间复杂度均为 **$O(1)$** 的 LRU 缓存,单靠一种数据结构是无法做到的。我们需要结合**哈希表**和**双向链表**: 1. **哈希表**: * **作用**:存储 `key` 到链表节点地址的映射。 * **优势**:可以在 $O(1)$ 的时间内判断 `key` 是否存在,并快速定位到链表中的对应节点。 2. **双向链表**: * **作用**:维护数据的使用时间顺序。链表头部表示**最近使用**的数据,链表尾部表示**最久未使用**的数据。 * **优势**:在已知节点地址的情况下,双向链表可以在 $O(1)$ 时间内完成节点的插入、删除和移动。双向链表使得我们在移动节点时不需要遍历寻找前驱节点。 3. **哨兵节点**: * 为了简化链表为空或只有一个节点时的边界处理逻辑,我们引入两个哨兵节点:`head`(伪头部)和 `tail`(伪尾部)。真正的数据节点将始终在这两个哨兵节点之间活动。 ### 二、 时间复杂度分析 * **`get(key)`:$O(1)$** * 通过哈希表查找 `key`,时间复杂度为 $O(1)$。 * 若存在,将其在双向链表中对应的节点移动到头部。由于已知该节点的确切位置,修改前后节点的 `prev` 和 `next` 指针仅需 $O(1)$ 时间。 * **`put(key, value)`:$O(1)$** * **若 `key` 已存在**:哈希表查找 $O(1)$,更新链表节点的值并将其移动到头部 $O(1)$。 * **若 `key` 不存在**:创建新节点并插入哈希表 $O(1)$,将新节点添加到链表头部 $O(1)$。 * **若触发容量上限淘汰**:直接通过伪尾节点 `tail.prev` 找到最久未使用的节点,删除哈希表中的对应项 $O(1)$,并在链表中摘除该节点 $O(1)$。 ### 三、 代码实现 ```python class DLinkedNode: """双向链表节点""" def __init__(self, key=0, value=0): self.key = key self.value = value self.prev = None self.next = None class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} # 哈希表:key -> DLinkedNode # 初始化伪头部和伪尾部节点 self.head = DLinkedNode() self.tail = DLinkedNode() self.head.next = self.tail self.tail.prev = self.head def get(self, key: int) -> int: if key not in self.cache: return -1 # 若 key 存在,先通过哈希表定位,再移到头部 node = self.cache[key] self._move_to_head(node) return node.value def put(self, key: int, value: int) -> None: if key in self.cache: # 若 key 已经存在,更新 value 并移到头部 node = self.cache[key] node.value = value self._move_to_head(node) else: # 若 key 不存在,创建一个新的节点 new_node = DLinkedNode(key, value) # 加入哈希表 self.cache[key] = new_node # 添加至双向链表的头部 self._add_to_head(new_node) # 检查容量是否超出 if len(self.cache) > self.capacity: # 超出容量,删除双向链表的尾部节点 removed = self._remove_tail() # 删除哈希表中对应的项 del self.cache[removed.key] #...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【CLAUDE】这是一份高质量的LRU缓存实现。算法设计采用经典的哈希表+双向链表方案,正确实现了O(1)的get/put操作,淘汰策略准确无误。代码结构清晰,注释详尽,测试用例覆盖了题目要求的边界场景(容量为1、缓存满时淘汰、更新已有key)。设计思路说明和时间复杂度分析专业到位,完全满足题目的所有要求,是一个接近满分的标准答案。 【GEMINI】这是一份教科书级别的 LRU 缓存实现。不仅在算法设计上完全符合 O(1) 的性能要求,在工程实践上也表现出色,文档说明清晰,测试用例完备,充分体现了资深后端工程师的专业素养。 【KIMI】总体而言,提供的代码实现了LRU缓存算法,并且具有较高的工程质量。代码结构清晰,注释充分,测试用例覆盖了不同的场景。但是,在测试用例的实现方面还有改进的空间,可以考虑使用更健壮的测试框架。

进阶难度评测结果

  • 得分:85.1 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

这里为您提供一个完整、高性能且线程安全的 LRU 缓存系统的 Python 实现。该实现严格遵循了您的所有要求,并附带了详细的架构说明和测试用例。 ### 1. 完整代码实现 ```python import threading import time from collections import OrderedDict from typing import Any, Dict, List, Optional class LRUCache: """ 支持TTL和线程安全的LRU缓存系统 """ def __init__(self, capacity: int): if capacity Any: """获取缓存值,若 key 不存在或已过期返回 -1。时间复杂度 O(1)""" with self._lock: if key not in self.cache: self._miss_count += 1 return -1 value, expire_at = self.cache[key] current_time = time.time() # 惰性删除:检查是否过期 if expire_at is not None and current_time > expire_at: # 已过期,删除条目并记录未命中 del self.cache[key] self._miss_count += 1 return -1 # 缓存命中,移动到链表尾部(表示最近使用) self.cache.move_to_end(key) self._hit_count += 1 return value def put(self, key: str, value: Any, ttl: Optional[float] = None) -> None: """写入缓存,ttl 单位为秒(None 表示永不过期)。时间复杂度 O(1)""" with self._lock: expire_at = time.time() + ttl if ttl is not None else None if key in self.cache: # Key已存在,更新值、过期时间,并移动到尾部 self.cache[key] = (value, expire_at) self.cache.move_to_end(key) else: # Key不存在,检查容量 if len(self.cache) >= self.capacity: # 缓存已满,淘汰链表头部(最久未使用) # 注意:这里淘汰的可能是已过期但未被惰性删除的条目,符合LRU和O(1)要求 self.cache.popitem(last=False) # 插入新条目 self.cache[key] = (value, expire_at) def delete(self, key: str) -> None: """主动删除指定 key""" with self._lock: if key in self.cache: del self.cache[key] def batch_get(self, keys: List[str]) -> Dict[str, Any]: """批量获取,返回 {key: value} 字典,过期或不存在的 key 不包含在结果中""" result = {} with self._lock: current_time = time.time() for key in keys: if key in self.cache: value, expire_at = self.cache[key] # 惰性删除检查 if expire_at is None or current_time None: """批量写入,所有 key 使用相同的 ttl""" with self._lock: expire_at = time.time() + ttl if ttl is not None else None for key, value in items.items(): if key in self.cache: self.cache[key] = (value, expire_at) self.cache.move_to_end(key) else: if len(self.cache) >= self.capacity: self.cache.popitem(last=False) self.cache[key] = (value, expire_at) def purge_expired(self) -> None: """主动扫描并清除所有过期条目"""...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【CLAUDE】候选输出整体质量较高,实现了题目要求的所有核心功能。最值得称道的是选择threading.Lock并内联batch操作逻辑的设计决策,避免了RLock的重入开销,体现了对性能的深入思考。设计说明文档详尽,复杂度分析准确,TTL策略权衡说明到位。主要不足:测试用例中stats断言的数字存在轻微逻辑错误,delete方法缺少返回值,purge_expired的实现方式(重建整个OrderedDict)相比逐个删除略显低效。与参考答案相比,整体实现路径不同但同样合理,是一份高质量的工程实现。 【GEMINI】这是一个非常专业的实现,完全符合资深后端工程师的职级定位。模型不仅准确完成了所有功能点,还在并发控制上展现了深厚的功底,通过内联逻辑优化锁的选择,体现了对性能和线程安全机制的深刻理解。代码结构清晰,测试充分,复杂度分析准确,是一份高质量的 AI 生成结果。 【KIMI】候选人提供的代码在算法正确性和线程安全方面表现尚可,基本实现了LRU缓存和TTL过期的功能,但在工程化质量方面存在一些问题,特别是在批量操作和统计功能的实现上。代码的测试覆盖度也有待提高。建议候选人进一步优化代码实现,提高测试的覆盖度和准确性。

困难难度评测结果

  • 得分:90.4 分
  • 通过状态:已通过

模型生成产物

以下是该模型针对此任务的实际生成内容:

# 分布式缓存系统核心组件设计与实现 ## 1. 设计说明与复杂度分析 本系统采用分层架构设计,主要分为:一致性哈希层、节点管理层、本地缓存层、数据同步层和监控统计层。 ### 模块划分及复杂度 | 模块 | 核心职责 | 时间复杂度 | 空间复杂度 | | :--- | :--- | :--- | :--- | | **ConsistentHashRing** | 数据分片、虚拟节点映射、负载统计 | 查找/添加/删除: **O(log VN)**,VN为虚拟节点总数 | **O(VN)** 存储虚拟节点映射 | | **CacheNode** | 节点健康状态、心跳、本地缓存容器 | 心跳检测: **O(1)** | **O(C)** C为节点容量上限 | | **EvictionStrategy** | 淘汰算法策略(LRU/LFU/FIFO) | Get/Put: **O(1)** | **O(C)** 存储键值及指针 | | **ReplicationManager** | 异步复制、最终一致性、同步日志记录 | 写入触发: **O(R)**,R为副本因子 | **O(W)** W为待复制的写操作量 | | **DistributedCache** | 门面类,路由、故障转移、防异常穿透 | 路由与故障转移: **O(log VN)** | **O(N)** N为物理节点数 | *注:由于一致性哈希采用红黑树/二分查找(Python中为SortedList+bisect),路由复杂度为O(log VN)。本地缓存操作通过手写双向链表+哈希表实现O(1)。* --- ## 2. 完整代码实现 ```python import hashlib import bisect import threading import time import random import logging from abc import ABC, abstractmethod from collections import defaultdict from sortedcontainers import SortedList from concurrent.futures import ThreadPoolExecutor logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # ==================== 1. 淘汰策略模式实现 ==================== class Node: """双向链表节点""" __slots__ = ['key', 'value', 'prev', 'next', 'freq'] def __init__(self, key, value): self.key = key self.value = value self.prev = None self.next = None self.freq = 1 class DoublyLinkedList: """手写双向链表,满足O(1)插入删除要求""" def __init__(self): self.head = Node(None, None) self.tail = Node(None, None) self.head.next = self.tail self.tail.prev = self.head self.size = 0 def append_to_head(self, node): node.next = self.head.next node.prev = self.head self.head.next.prev = node self.head.next = node self.size += 1 def remove_node(self, node): node.prev.next = node.next node.next.prev = node.prev self.size -= 1 def remove_tail(self): if self.size == 0: return None node = self.tail.prev self.remove_node(node) return node class EvictionStrategy(ABC): @abstractmethod def get(self, key): pass @abstractmethod def put(self, key, value): pass @abstractmethod...

AI 评审点评

以下是 AI 评审对该模型输出的点评:

【CLAUDE】这是一份高质量的分布式缓存系统实现。代码展现了扎实的算法功底(手写 O(1) LRU/LFU/FIFO)、清晰的架构设计(策略模式+分层架构)和深入的分布式系统理解(CAP 理论、异常防护、故障转移)。核心优势包括:1) 一致性哈希实现正确且高效,虚拟节点机制保证负载均衡;2) 三种淘汰策略均严格满足 O(1) 复杂度要求,未使用标准库封装;3) 异步复制与故障转移逻辑完整,提供最终一致性保证;4) 分布式异常预防方案全面,结合 CAP 理论的 Trade-off 分析深度优秀;5) 单元测试覆盖关键场景。改进空间:1) 一致性哈希环的读操作可使用读写锁优化并发性能;2) 缺少热点 key 的并发击穿保护实现;3) 布隆过滤器等高级防护机制未落地到代码;4) 节点动态增删后的数据迁移逻辑缺失。总体而言,该实现在算法正确性、并发安全性和架构设计上均达到了生产级水准,是一份优秀的分布式缓存系统核心组件实现。 【GEMINI】这是一份高质量的分布式缓存系统设计方案。代码实现严谨,不仅满足了所有功能性约束(尤其是手动实现 O(1) LFU 和禁止使用 OrderedDict),还在系统健壮性(心跳、故障转移)和监控维度上有完整的考虑。文档部分对 Trade-off 的分析深入浅出,体现了资深架构师的水平。单元测试覆盖全面,逻辑闭环。 【KIMI】整体而言,该分布式缓存系统的核心组件实现在算法正确性、并发性能、系统架构设计等方面表现优秀。一致性哈希和淘汰策略的实现满足要求,线程安全性和异步复制机制合理。系统架构设计考虑了可扩展性和分布式异常场景的预防,CAP 理论的应用体现了对分布式系统设计的深入理解。但仍有进一步提升空间,如在性能优化、锁竞争减少等方面。

相关链接

您可以通过以下链接查看更多相关内容:

加载中...