快速数据传输
项目描述
xpdt:快速数据传输
关于
xpdt 是(另一种)语言,用于定义数据类型并生成用于序列化和反序列化它们的代码。它旨在以很少或没有开销的方式生成代码,并基于允许零拷贝反序列化和(至多)单拷贝写入(源到缓冲区)的固定长度表示。
尤其是生成的 C 代码经过高度优化,通常允许消除写入时的数据复制,并支持优化,例如固定长度对象的循环展开。这可能导致每秒超过 5 亿个对象的读取速度(每个对象约 1.8 纳秒)。
例子
xpdt 源语言看起来类似于 C 结构定义:
struct timestamp {
u32 tv_sec;
u32 tv_nsec;
};
struct point {
i32 x;
i32 y;
i32 z;
};
struct line {
timestamp time;
point line_start;
point line_end;
bytes comment;
};
支持从 8 位到 128 位的固定宽度整数类型,以及
bytes类型,它是一个可变长度的字节序列。
目标语言
当前支持以下目标语言:
- C
- Python
C 代码经过高度优化。
Python 代码已尽我所能针对 CPython 进行了优化。它使用类型化NamedTuple的对象,这比常规元组有一些小的开销,它用于struct.Struct进行打包/解包。考虑到设计限制,我还将生成的字节码编码为我认为最小的。因此,纯 Python 代码的性能与用 C 或 Rust 实现的 JSON 库相当。
为了在 Python 中获得更好的性能,可能需要开发一个 Cython 目标。在某些情况下,CFFI 结构可能更高效,因为它们可以避免为每个记录创建/销毁对象。
目标语言纯粹作为jinja2模板实现。
序列化格式
固定长度对象的序列化格式只是一个打包的 C 结构。
对于任何包含bytes类型字段的对象:
- 32 位无符号记录长度附加到结构
- 所有
bytes类型字段都转换为u32并包含字节的长度 - 所有字节内容按照它们出现的顺序附加在结构之后
例如,按照上面的示例,序列化将是:
u32 tot_len # = 41
u32 time.tv_sec
u32 time.tv_usec
i32 line_start.x
i32 line_start.y
i32 line_start.z
i32 line_end.x
i32 line_end.y
i32 line_end.z
u32 comment # = 5
u8 'H'
u8 'e'
u8 'l'
u8 'l'
u8 'o'
特征
到目前为止,该功能集非常苗条。
没有数组/序列/映射类型,也没有键控联合。
如果存在合适的实现,将来可能会添加对此类事物的支持。如果满足以下条件,则适合实施:
- 它承认零(或接近零)开销实现
- 不使用该功能时不会产生任何开销
执照
编译器是在 GPLv3 下发布的。
C 支持代码/头文件是在 MIT 许可下发布的。
生成的代码是你的。