Skip to content

【开源自荐】LJSON:全能、高性能、真流式的 C 语言 JSON 引擎和数值引擎 #249

@lengjingzju

Description

@lengjingzju

LJSON:全能、高性能、真流式的 C 语言 JSON 引擎和数值引擎

0 项目地址

LJSON 支持 Windows 和 Linux ,项目地址位于:

1. 项目定位与设计初衷

LJSON 诞生于 2019 年 10 月,比 yyjson 早一年,初衷并非单纯追求基准测试中的极限解析速度,而是要在 性能、内存占用、可编辑性、流式能力、可维护性 之间找到最佳平衡。

它目前状态是:

  • 能在多数场景下媲美甚至超越 yyjson 的性能
  • 提供 yyjson 架构无法小改实现的真流式处理能力
  • 保持代码可读性和可扩展性,适合长期演进

2. 核心能力

双重核心

全能 JSON 处理

  • 完整支持 JSON5 规范(十六进制、注释、尾逗号、单引号等)
  • DOM / SAX 双解析模式
  • 真流式文件(边读边解析,边写边打印)

高性能数值转换引擎

  • 独创 ldouble 算法
  • 浮点 ↔ 字符串转换性能远超标准库和主流算法(sprintf、grisu2、dragonbox)
  • 精度是16位,在边界处理时追求最短而不是偶数(标准是16位或17位,取决于二进制指数转换为十进制指数的乘子的分辨率)

3. 架构与模式设计

LJSON 提供 7 种解析模式4 种打印模式,覆盖从内存到文件、从 DOM 到 SAX 的全场景需求:

解析模式

  1. DOM 经典模式(malloc/free)
  2. DOM 内存池模式
  3. DOM 复用模式(可编辑,字符串原地复用)
  4. DOM 文件流模式(真流式)
  5. DOM 文件流内存池模式(真流式 + 内存池)
  6. SAX 模式(回调处理)
  7. SAX 文件流模式(真流式 + 回调)

打印模式

  1. DOM → 字符串
  2. DOM → 文件(真流式)
  3. SAX → 字符串
  4. SAX → 文件(真流式)

真流式:边读文件边解析,边打印边写文件,无需完整读入或生成中间大缓冲,内存占用可降至常数级,即使处理 1GB JSON 文件也仅需 KB 级内存。

yyjson ≈ LJSON 的 DOM 复用模式 + 激进只读优化

4. 与 yyjson 的设计差异

核心差异包括:

维度 LJSON yyjson
模式设计 多模式(含真流式、可编辑复用) 单一复用模式(只读优化)
可编辑性 复用模式可编辑 只读与可编辑严格分离(val / mut_val)
字符串存储 标准 C 字符串(尾 1 个 \0 非标准尾 4 个 \0(减少边界判断)
对象存储 key 与 value 一起存储 key 与 value 分开存储
内存策略 按需分配,尽量避免浪费 大块预分配,冗余度高
访问加速 json_items_t 缓存,数组 O(1)、对象 O(logN) 未知是否有缓存,可能 O(N)/O(2N)
优化手法 内联、分支预测、查表、缓存元信息;保持可读性 同类优化 + 大量宏循环展开,代码晦涩
流式处理 真流式解析/打印 不支持

5. 性能来源与权衡

优化技术对比

两者都使用:

  • 内存池(块)优化
  • 内联优化(inline)
  • 分支预测优化(likely/unlikely)
  • Cache 命中优化
  • 查表优化
  • 拷贝优化
  • 信息记录优化(缓存字符串长度等)

差异:

  • yyjson:大量宏进行循环手动展开,代码紧凑但晦涩,性能更激进;使用非标准特性(尾后 4 个 \0、非对齐访问等)。
  • LJSON:追求易维护、可扩展、低占用、高性能的工程化平衡。保持可读性,宏进行手动循环展开。

性能对比

yyjson 相当于只实现了 LJSON 的DOM复用模式,并且转换可编辑模式时对象和字符串都存储在内存块里,和LJSON的内存池原理一致。

  • yyjson 只读复用模式 性能略高于 LJSON,来源于:
    • 模式单一
    • 激进资源使用(预分配冗余内存)
    • 非标准特性(尾后 4 个 \0、非对齐访问)
    • 宏循环展开
  • yyjson 只读模式 性能和 LJSON 很接近,两者互有胜负
  • yyjson 可编辑模式 性能可能大幅落后于 LJSON(大文件解析 yyjson 比 LJSON 内存占用多约一倍,速度慢约一倍

注:如果 LJSON 放弃流式、标准字符串、可编辑性,采用更晦涩代码,可达到 yyjson 只读复用模式 性能,但那将不再是 LJSON 的设计哲学。

6. 优化机制亮点

  • 零堆分配:首次分配后循环复用,避免频繁 malloc/free。
  • 原地字符串复用:直接引用输入缓冲区,减少拷贝与内存带宽消耗。
  • json_items 加速器:数组 O(1) 访问,对象 O(logN) 查找。
  • 真流式管线:解析与 I/O 并行,消除峰值内存与额外拷贝。
  • ldouble 数值引擎:浮点转字符串性能领先 sprintf 10~70 倍。

7. 多维度对比(可编辑模式)

对比维度 LJSON yyjson RapidJSON cJSON
解析性能 高(547ms,可编辑复用) 中高(1011ms,可编辑) 较高 中等
打印性能 高(真流式+ldouble) 高(全缓冲) 中等
内存占用 可常数级(流式) 较高 较高 较高
CPU 特性依赖
可扩展性
代码可读性 极低
关键机制 零堆分配、内存池复用、原地字符串、json_items、ldouble 原地复用、内存块、非标准字符串尾、循环展开 模板+分配器 malloc/free

8. 适用场景

  • 大文件处理:GB 级 JSON 格式化/压缩,内存占用可常数级。
  • 嵌入式系统:低内存、高性能需求。
  • 高频读写:实时数据流解析与生成。
  • 跨平台开发:Linux / Windows / 嵌入式 RTOS。

9. 设计哲学总结

yyjson:以极致性能为第一目标,通过激进优化手段和单一模式深耕,适合极限只读解析场景。
LJSON:追求易维护、可扩展、低占用、高性能的工程化平衡,适合通用、可编辑、流式处理、大文件低内存占用的场景。纯 C 实现,零第三方依赖,跨平台编译,接口设计参考 cJSON,逻辑清晰,编译速度快,易于二次开发。

LJSON 的价值不仅在于跑分,更在于它能在真实工程环境中,以极低的内存占用和高性能,稳定支撑多样化的 JSON 处理需求。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions