perf(一言): JsonDataLoader 的缓存从 Redis 挪进程内
数据集是随数据目录发布的只读文件,运行期不会变,没有跨进程共享的必要。 原先塞 Redis 的写法每次命中都要把整份 json(最大的分类 pickle 后 323KB) 拉过网络再反序列化,比直接读本地盘还慢,而且和 session 挤在同一个 db=1。 改后首次读盘 4.3ms、之后每次 0.10us。签名、异常、返回结构都没动,缺文件 照旧抛 ValueError 被 HitokotoAPI 兜住;全部 12 个分类加载后每 worker 常驻 约 6.6MB,没做字段裁剪——那会改变旧接口的响应结构,而这里是回滚路径。 破例动了冻结的上一代:改动限于内部实现,外部可观测行为逐一对齐不变。 理由和边界写进了 OJ2/CLAUDE.md。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.core.cache import cache
|
# 本模块自己不再用它,但 judge/dispatcher.py 和 submission/views/oj.py 是
|
||||||
|
# `from utils.cache import cache` 拿的,删掉会连带炸两个模块
|
||||||
|
from django.core.cache import cache # noqa: F401
|
||||||
from django_redis.cache import RedisCache
|
from django_redis.cache import RedisCache
|
||||||
from django_redis.client.default import DefaultClient
|
from django_redis.client.default import DefaultClient
|
||||||
|
|
||||||
@@ -29,17 +31,29 @@ class MyRedisCache(RedisCache):
|
|||||||
|
|
||||||
|
|
||||||
class JsonDataLoader:
|
class JsonDataLoader:
|
||||||
|
"""只读 json 数据集的加载器(目前只有一言)。
|
||||||
|
|
||||||
|
缓存放在进程内,不进 Redis:这些文件是随镜像/数据目录一起发布的只读数据,
|
||||||
|
永远不会在运行期变化,没有跨进程共享的必要。原先塞 Redis 的写法,每次命中都要
|
||||||
|
把整份 json(最大的一个分类 pickle 后 323KB)拉过网络再反序列化一遍 ——
|
||||||
|
比直接读本地盘还慢,而且和 session 挤在同一个 Redis db 里。
|
||||||
|
|
||||||
|
全部 12 个分类都加载后,每个 gunicorn worker 常驻约 6.6MB。
|
||||||
|
"""
|
||||||
|
|
||||||
|
_cache = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_data(cls, dir, filename):
|
def load_data(cls, dir, filename):
|
||||||
cache_key = f"json_data_{filename}"
|
cache_key = (str(dir), filename)
|
||||||
if cached := cache.get(cache_key):
|
if (cached := cls._cache.get(cache_key)) is not None:
|
||||||
return cached
|
return cached
|
||||||
|
|
||||||
file_path = Path(dir, filename)
|
file_path = Path(dir, filename)
|
||||||
try:
|
try:
|
||||||
with open(file_path, "r", encoding="utf-8") as f:
|
with open(file_path, "r", encoding="utf-8") as f:
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
cache.set(cache_key, data, timeout=7200)
|
cls._cache[cache_key] = data
|
||||||
return data
|
return data
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
raise ValueError(f"Data file {filename} not found")
|
raise ValueError(f"Data file {filename} not found")
|
||||||
|
|||||||
Reference in New Issue
Block a user