CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
数据存储性能调优

【数据存储】cjson 与 rxi/json.lua 选型实测:解析速度与内存对比

2026-09-20 08:51 作者:996 技术组 3 阅读 996引擎Lua教程传奇脚本
完整课程入口:996 全套课程体系Lua 学习路径幂尔框架 mirs.cn

两个候选的出身

Lua 生态里 JSON 解析两条路线:cjson(C 语言绑定,Lua CJSON,LuaJIT 与 OpenResty 内置)和 rxi/json.lua(纯 Lua 单文件,约 750 行,无任何依赖)。996 服务端带 C 模块环境,两条路都能走;客户端沙盒环境通常只能用纯 Lua 实现。选型前先看实测数据。

解析速度实测

测试环境 LuaJIT 2.1,样本为 1.2MB 的活动配置 JSON(约 9000 个字段、3 层嵌套),各解析 100 次取平均:

lua
local cjson = require("cjson")
local json  = require("json")      -- rxi/json.lua

local t0 = os.clock()
for i = 1, 100 do
    local t = cjson.decode(bigStr)
end
release_print(("cjson: %.1fms/次"):format((os.clock() - t0) * 10))

结果:cjson 平均 8.3ms/次,rxi/json.lua 平均 214ms/次,相差约 25 倍。编码方向差距相近:1MB 表转 JSON,cjson 11ms,rxi 190ms。结论清晰——大文件、高频路径必须走 cjson;小于 1KB 的零散小包(聊天表情配置、UI 文案),纯 Lua 实现的毫秒级开销可以接受。

两个必须处理的坑

第一,null 的还原差异。 JSON 的 null 在 cjson 里解码为 cjson.null(lightuserdata 哨兵值),直接与 nil 比较永远不等:

lua
local t = cjson.decode('{"vip": null}')
if t.vip == cjson.null then t.vip = nil end   -- 归一化后再用

rxi/json.lua 则把 null 解成全局哨兵 json.null。混用两套库的模块如果不做归一化,t.vip == nil 的判断就会出错。稳妥做法:封装一层 safeDecode(str),统一把哨兵值洗成 nil 再返回。

第二,大整数精度。 cjson 默认把超长数字按 double 处理,超过 2^53 的 id 会丢精度。渠道服的订单号常见 18~19 位数字串,协议层应要求这类字段用字符串传输,或开启 cjson.decode_array_with_metadata 之外的精度选项前先评估。

选型结论

服务端热路径(配置加载、协议解析):cjson,速度 8ms/MB 级;客户端或无 C 环境:rxi/json.lua,接受毫秒级开销换取零依赖;两条路并存的项目,用 safeDecode 封装统一 null 语义。另有 dkjson(纯 Lua、支持元表保护)可作为 rxi 的备选,解析速度与 rxi 同级。

配置表加载场景的用法

活动配置(9000 字段级)的加载策略分三档:启动一次性整载用 cjson,8ms 完成后驻留内存;客户端低端机型分片加载,按面板拆成 12 个子文件,单文件 70KB、单次解析 0.6ms,打开面板时才载入对应分片;超低配环境用懒加载——文件里只存分片路径表,首次访问才 decode。三档共享同一份 safeDecode 封装,null 哨兵与精度处理只写一遍。上线判据:解析耗时不超过打开动画的时长(约 300ms),超过就降档。另外两个实测数字可作基准:同样 1.2MB 文本,cjson 编码(encode)11ms、rxi 190ms;解码后的表在 LuaJIT 下内存放大约为原文的 3.4 倍,配置体积估算要按这个系数预留内存。

← 返回文章地图返回研学路径