fblualib fb.thrift 序列化指南:如何高性能序列化任意 Lua 对象(含循环引用)
【免费下载链接】fblualibFacebook libraries and utilities for Lua项目地址: https://gitcode.com/gh_mirrors/fb/fblualib
fblualib 是 Facebook 开源的 Lua / Torch 工具库合集,其中的fb.thrift模块可以高性能地序列化和反序列化任意 Lua 对象——table、带 upvalue 的函数、torch Tensor,甚至包含循环引用的对象图,反序列化后引用关系会被完整还原。本指南带你快速上手 fb.thrift 序列化。
1. fb.thrift 能解决什么问题?
Torch 自带的torch.serialize功能有限且速度较慢。fb.thrift 基于 Thrift 格式 + folly 压缩库实现,带来三大优势:
- ✅任意对象图:支持循环引用(A 指向 B,B 又指回 A),引用关系精确还原
- ✅可选压缩:内置 NONE / LZ4 / SNAPPY / ZLIB / LZMA2 五种编解码器
- ✅自定界格式:同一文件可连续序列化多个对象,无需手动加帧头
- ✅C++ 互操作:支持从 C++ 侧直接读写标量和张量(见 fblualib/thrift/LuaObject.h)
支持的类型一览:
| 类型 | 是否支持 | 说明 |
|---|---|---|
| nil / number / boolean / string | ✅ | 原始类型直接编码 |
| table(含稀疏表) | ✅ | 键按 列表/字符串/整数/布尔 分组存储 |
| function | ✅ | 序列化为字节码 + upvalues(跨 LuaJIT 大版本不兼容时会检查报错) |
| torch Tensor / Storage | ✅ | 二进制数据高效编码 |
| torch.class / pl.class 对象 | ✅ | 按类名识别,只存数据成员不存方法 |
| coroutine | ❌ | 协程不可序列化 |
2. 一键安装步骤
- 环境要求:LuaJIT + Torch,仅支持 x86_64 Linux
- 获取代码:
git clone https://gitcode.com/gh_mirrors/fb/fblualib cd fblualib/thrift- CMake 构建:模块依赖 Folly、Glog、Thrift、Torch,构建脚本位于 fblualib/thrift/CMakeLists.txt,会生成共享库
fblualib_thrift和 Lua 模块fb/thrift/lib,并自动安装到 Torch 的 rock 目录,之后即可require('fb.thrift')。
💡 压缩器是否可用取决于构建 folly 时系统装了哪些压缩库,
thrift.codec表会列出实际可用的选项。
3. 快速上手:4 个核心函数
接口极其简洁,全部在 fblualib/thrift/fb/thrift/init.lua 中定义:
local thrift = require('fb.thrift') local obj = { foo = 2 } -- 任意 Lua 对象 -- 序列化:to Lua 字符串 / to 已打开的文件 local str = thrift.to_string(obj) local f = io.open('/tmp/foo', 'wb') thrift.to_file(obj, f) -- 反序列化:from 字符串 / from 文件 local obj2 = thrift.from_string(str) local obj3 = thrift.from_file(f)几个实用细节:
to_file/from_file基于文件指针当前位置读写,格式自定界——同一文件可以连续序列化多个对象,读取时自动跳过对象边界- 格式自定界特性在 fblualib/thrift/test/thrift_test.lua 的
testThriftSerializationToFile中有完整验证
4. 循环引用如何正确还原?
这是 fb.thrift 序列化最有价值的特性。所有引用类型对象都会登记到内部的 refs 表(ID 定义在 fblualib/thrift/if/LuaObject.thrift 的LuaRefList中),再次遇到同一对象时只写一个索引引用。反序列化时按索引回填,因此:
local a = {'hello', 'world'} local b = {a, a} b[1] = b -- 制造循环引用 local r = thrift.from_string(thrift.to_string(b)) assert(r[1] == r) -- 循环引用原样还原!测试里甚至特意注释了 "assertEquals will overflow the stack here"——深度循环引用会让常规比较函数栈溢出,但 fb.thrift 序列化/反序列化本身完全不受影响。
5. 如何选择压缩编解码器?
序列化函数可传第二个参数指定thrift.codec:
| 编解码器 | 压缩比 | 速度 | 适用场景 |
|---|---|---|---|
NONE(默认) | 无 | 最快 | 内存传输、小对象 |
LZ4 | 中等 | 极快 | 高速网络传输 |
SNAPPY | 中等 | 极快 | 通用默认压缩 |
ZLIB | 较高 | 中等 | 需要兼顾压缩比与速度 |
LZMA2 | 最高 | 最慢 | 磁盘存储、日志归档 |
-- 最高压缩比(如持久化到磁盘) thrift.to_file(obj, f, thrift.codec.LZMA2) -- 最快(如 RPC 传输大张量) thrift.to_file(obj, f, thrift.codec.LZ4)C++ 侧的编解码实现见 fblualib/thrift/Encoding.cpp,采用分块压缩(chunked compression)设计,大对象可流式处理而不必一次性读入内存。
6. 进阶技巧
6.1 跳过不该序列化的东西:envs 外部环境
to_string/to_file的第三个参数envs(表 of 表)中出现的对象不会被序列化,只记录引用位置;反序列化时传入相同的 envs即可还原:
thrift.to_string(foo, thrift.codec.NONE, {package.loaded, {pl}}) thrift.from_string(str, {package.loaded, {pl}})典型用途:函数 upvalue 里引用的模块(如pl、thrift自身)不需要重复打包,还能让反序列化后的函数直接复用已加载的模块实例。
6.2 Torch / Penlight 类的自定义序列化
Torch 对象默认只序列化数据成员 + 类型名(不存方法)。若类定义了_thrift_serialize/_thrift_deserialize方法,可在序列化前替换为精简表或清理临时字段——示例见 fblualib/thrift/test/thrift_test.lua 中的ExplicitSerDe类。Penlight 类需先显式注册:
thrift.add_penlight_class(MyClass, '全局唯一名称')6.3 性能有多快?
项目自带 benchmark(testBM函数)将 fb.thrift 与torch.serialize对比:对 1 万个元素的 table 和 100×100 张量各做 10~10000 次序列化/反序列化,fb.thrift 在表序列化和张量序列化两个场景下均显著快于torch.serialize,验证了其 C++ 高性能内核的优势。
7. 相关源码导读
| 文件 | 作用 |
|---|---|
fblualib/thrift/fb/thrift/init.lua | Lua 接口层:to/from_string、to/from_file、OOP 回调注册 |
fblualib/thrift/if/LuaObject.thrift | Thrift IDL:对象图、refs 表、版本头定义 |
fblualib/thrift/Encoding.cpp/.h | 编码/解码核心,含字符串与文件两种 Reader/Writer |
fblualib/thrift/ChunkedCompression.* | 分块压缩支持 |
fblualib/thrift/Serialization.cpp/LuaSerialization.cpp | Lua C 模块绑定入口 |
fblualib/thrift/test/thrift_test.lua | 完整测试:循环引用、稀疏表、OOP、随机对象图、benchmark |
8. 总结
fb.thrift 序列化用 4 个函数(to_string / from_string / to_file / from_file)就覆盖了从内存字符串到文件 IO 的全部场景,天然支持循环引用对象图、函数字节码、torch 张量,并提供 5 种压缩编解码器按需权衡速度与体积。无论是持久化模型检查点、进程间传输复杂对象,还是替代 torch.serialize 提速,它都是 Lua 生态里值得收藏的高性能序列化方案 🚀
【免费下载链接】fblualibFacebook libraries and utilities for Lua项目地址: https://gitcode.com/gh_mirrors/fb/fblualib
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考