高性能多语言序列化框架 Fury

小夏 科技 更新 2024-01-29

github地址:

FURY是一个基于JIT动态编译和零拷贝的多语言序列化框架,提供极致的性能和易用性

它支持主流编程语言J**A、Python C++、Golang、J**Ascript,其他语言都可以轻松扩展。

统一的多语言序列化核心能力:

高度优化的序列化基元。

零拷贝序列化支持、带外序列化协议和堆外内存读/写支持。

基于JIT动态编译技术,异步多线程在运行时自动生成序列化,优化性能,增加方法内联,缓存和消除死,减少虚拟方法调用、条件分支、哈希查找、元数据写入、内存读写等。

多协议支持:将动态序列化的灵活性和易用性与静态序列化的跨语言功能相结合。

j**a 序列化:

无缝替代 JDK Kryo Hessian,无需修改任何内容**,但提供高达 170 倍的性能,可以大大提高高性能场景下 RPC 调用、数据传输和对象持久化的效率。

100%兼容JDK序列化,原生支持JDK自定义序列化方法:WriteObject ReadObject WriteReplace、ReadResolve、ReadObjectNoData

跨语言对象图序列化:

多语言 跨语言自动序列化任意对象,无需创建 IDL 文件、手动编译架构生成**以及将对象转换为中间格式。

多语言 自动序列化跨语言的共享引用和循环引用,而无需担心数据重复或递归错误。

支持对象类型多态性,可同时序列化多个子类型对象。

行内存序列化:

它提供了缓存友好的二进制随机存取行内存格式,支持跳过序列化和部分序列化,适用于高性能计算和大规模数据传输场景。

它支持使用箭头列存储进行自动转换。

** 作者 Nanqiu * Fury 序列化框架使用示例 * @slf4jpublic 类 furyexample ** 反序列化 * param bytes 字节数组 * 返回对象 * public static object deserialize(byte bytes) public static void main(string args)。", arrays.tostring(furyexample.serialize(furyobject)))furyobject furydeserialize = (furyobject)furyexample.deserialize(bytes); log.info("反序列化:[id:{}name:{}text:{}furyobject2:{}", furydeserialize.getid(),furydeserialize.getname(),furydeserialize.gettext(),furydeserialize.getfuryobject2())
FURY定义并实现了一套基本的序列化能力,基于这些能力可以快速构建不同的多语言序列化协议,并通过编译加速进行优化,实现高性能。 同时,一个协议在基础能力方面的性能优化,也可以使所有序列化协议受益。

序列化中涉及的常见操作包括:

位图位操作。

整数编解码器。

整数压缩。 字符串创建和复制优化。

字符串编码:ASCII UTF8 UTF16。

内存复制优化。

数组复制压缩优化。

元数据编码、压缩和缓存。

对于这些操作,Fury 对每种语言都做了大量的优化,结合 SIMD 指令和高级语言功能将性能推向极致,方便使用不同的协议。

在大规模数据传输场景中,一个对象图内部往往存在多个二进制缓冲区,序列化框架在序列化过程中会将这些数据写入中间缓冲区,引入多个耗时的内存副本。 Fury 借鉴了 pickle5、ray 和 arrow 的零拷贝设计,实现了一套带外序列化协议,可以直接捕获对象图中的所有二进制缓冲区,避免缓冲区的中间副本,并将序列化时的内存副本开销降低到 0。

Fury 在零拷贝序列化过程时关闭引用支持。 如图所示

目前,FURY 内置了对以下类型的零拷贝支持:

j**a:所有基本类型的数组,ByteBuffer、ArrowRecordBatch 和 VectorSchemaRoot。

python:所有数组、numpy 数组、pyarrowstable、pyarrow.recordbatch。

golang:byte slice。

用户还可以基于 Fury 界面扩展新的零拷贝类型。

对于要序列化的自定义类型对象,通常包含大量的类型信息,FURY利用这些类型信息在运行时直接生成高效的序列化,并在动态编译阶段完成大量的运行时操作,从而增加方法内联和缓存,减少虚拟方法调用、条件分支、哈希查找、元数据写入、 In-Memory 读写等,最终大大提升了序列化性能。

对于J**A语言,FURY实现了一套运行时生成框架,为序列化逻辑定义了一组算子表达式ir,在运行时基于对象类型的泛型信息进行类型推断,然后构建描述序列化逻辑的表达式树,并根据表达式树生成高效的j**a,然后在运行时通过Janino编译成字节码, 然后将其加载到用户的类加载器或 Fury 创建的类加载器中,最后通过 j**a jit 编译成一个高效的汇编。

由于 JVM JIT 会跳过大方法的编译和内联,因此 Fury 还实现了一套优化器,将大方法递归拆分为小方法,从而保证 FURY 生成的所有**都可以被编译和内联,将 JVM 的性能压缩到极致。

如图所示

同时,FURY还支持异步多线程动态编译,将不同序列化器的**生成任务提交到线程池中执行,并在编译完成前以解释模式执行,从而保证不会出现序列化故障,也无需提前预热所有类型的序列化。

由于序列化需要对每种编程语言的对象进行紧密的操作,而编程语言不暴露内存模型的底层 API,因此通过原生方法调用存在较大的开销,因此无法通过 LLVM 构建统一的序列化器 JIT 框架,但需要结合每种语言中的语言特性实现特定的**生成框架和序列化器构造逻辑。

虽然 JIT 编译可以大大提高序列化效率,并基于运行时数据的统计分布重新生成更好的序列化,但 C++ Rust 等语言不支持反射,没有虚拟机,也没有提供内存模型的底层 API,因此无法通过 JIT 动态编译为此类语言生成序列化。

对于此类场景,Fury 正在实现一个 AOT 静态生成框架,该框架在编译时根据对象的架构提前生成序列化,然后使用生成的序列化进行自动序列化。 对于 Rust,Rust 的宏也将在未来编译时生成,提供更好的易用性。

在序列化自定义类型时,会对字段进行重新排序,以保证同一接口类型的字段按顺序序列化,增加缓存命中的概率,同时也促进了 CPU 指令缓存,以实现更高效的序列化。 对于基本类型字段,写入顺序按字节字段大小的降序排序,这样如果起始地址对齐,后续的读写就会在内存地址对齐位置发生,CPU执行效率更高。

基于Fury提供的多语言序列化核心能力,在此基础上构建了三种序列化协议,适用于不同的场景

J**A 序列化:适用于纯 J**A 序列化场景,性能提升 100 倍以上。

跨语言对象图序列化:非常适合面向应用程序的多语言编程,以及高性能的跨语言序列化。

行内存序列化:适用于分布式计算引擎,如Spark Flink Dories Velox Sample Stream Processing Framework Feature Storage等。

此外,用户还可以基于 Fury 的序列化能力构建自己的协议。

由于 J**A 在大数据、云原生、微服务和企业级应用中的广泛应用,J**A 序列化的性能优化可以大大降低系统延迟,提高吞吐量,降低服务器成本。

这也是为什么 FURY 对 j**a 序列化做了大量极致的性能优化,使其具备以下能力:

极致性能:利用 J**A 对象的类型和泛型信息,结合 JIT 编译和不安全的低阶操作,Fury 的性能比 JDK 高出 170 倍,比 Kryo Hessian 性能高出 50 100 倍。

100% JDK 序列化 API 兼容性:支持所有 JDK 自定义序列化方法 WriteObject、ReadObject WriteReplace、ReadResolve、ReadObjectNoData 的语义,保证在任何场景下替换 JDK 序列化的正确性。 现有的 J**A 序列化框架(如 Kryo Hessian)在这些场景中存在一定的正确性问题。

后向兼容:如果反序列化端和序列化端的类架构不一致,仍然可以正确反序列化,可以独立升级部署应用,可以独立添加或删除字段。 此外,元数据被极度压缩和共享,与类型一致模式相比,类型兼容模式几乎没有性能损失。

元数据共享:元数据(类名、字段名、最终字段类型信息等)在某个上下文(TCP连接)的多个序列化之间共享,该上下文中第一次序列化时会将这些信息发送给对等方,对等方可以根据类型信息重建同一个反序列化程序。

零拷贝支持:支持带外零拷贝和堆外内存读/写。

跨语言对象图序列化主要应用于对动态性和易用性要求较高的场景。 尽管 Protobuf Flatbuffer 等框架提供了多语言序列化功能,但仍存在一些缺点:

IDL 需要提前编写并静态编译生成**,不够动态和灵活。

生成的类不符合面向对象的设计,无法向类添加行为,并且不能直接用作多语言应用程序开发的域对象。

不支持子类序列化。 面向对象编程的主要特点是通过接口调用子类方法。 这种类型的模型也没有得到很好的支持。 虽然 flatbuffer 提供了联合,但 protobuf 提供了任意功能之一,这需要在序列化和反序列化时确定对象的类型,这与面向对象编程的设计不符。

不支持循环和共享引用,需要重新定义一组领域对象的 idl,并自行实现引用解析,然后用每种语言编写 **,实现领域对象和协议对象之间的转换,如果对象图的嵌套层数较深,则需要编写更多**。

结合以上几点,FURY实现了一套跨语言的对象图序列化协议:

多语言 跨语言自动序列化任意对象:在序列化和反序列化端定义两个类,自动将一种语言的对象序列化为另一种语言的对象,无需创建 IDL 文件、编译架构生成和转换手写内容。

多语言:跨语言自动序列化共享引用和循环引用。

支持对象类型多态性,符合面向对象的编程范式,可以同时自动对多个子类型对象进行反序列化,无需用户手动处理。

同时,我们也支持该协议的带外零拷贝

自动跨语言序列化示例:

对于高性能计算和大规模数据传输场景,数据序列化和传输往往是整个系统的性能瓶颈。 如果用户只需要读取部分数据,或根据对象的字段进行筛选,则反序列化整个数据将产生额外的开销。 因此,Fury 还提供了一组二进制数据结构,可以直接对二进制数据进行读写,避免序列化。

Apache Arrow 是一种成熟的列存储格式,支持二进制读取和写入。 但是,列存储并不能满足所有场景的需求,链路和流计算场景中的数据自然是行存储结构,当涉及到数据变化和哈希联接聚合操作时,列计算引擎也会使用行存储结构。

Spark Flink Doris Velox 等计算引擎定义了一组 rowstore 格式,不支持跨语言,只能由自己的引擎内部使用,不能在其他框架中使用。 FlatBuffer 虽然可以支持按需反序列化,但需要静态编译 schema IDL 和管理偏移量,无法满足复杂场景的动态易用需求。

因此,在早期,Fury 借用了 Spark Tungsten 和 Apache Arrow 格式,实现了一套可以随机访问的二进制行内存结构,现在实现了 J**A Python C++ 版本,实现了对二进制数据的直接读写,避免了所有序列化开销。

fury row 格式的二进制格式,如图所示:

该格式存储密集,数据对齐,缓存友好,读/写速度更快。 通过避免反序列化,可以降低 J**A GC 压力。 同时,它降低了 Python 的开销,并且由于 Python 的动态性质,Fury 的数据结构实现了 getattr getitem slice 等特殊方法,以确保行为与 Python dataclass list 对象一致,用户没有任何意识。

以下是一些j**a序列化的性能数据,其中标题为compatible的图表为受支持类型兼容性下的性能数据,不包含compatible的图表为不支持类型兼容性下的性能数据。 公平地说,所有测试狂怒都关闭了零拷贝功能。

注:本文主要参考《狂暴》作者杨朝坤的阿里云社区博文。

阅读推荐]更多精彩内容,如:

Redis 系列。

数据结构和算法。

NACOS系列。

MySQL系列。

JVM 系列。

卡夫卡系列。

请移至【南秋】个人主页参考。 内容不断更新。

关于作者]热爱科技、热爱生活的老宝贝,专注J**A领域,关注【南秋同学】带你一起学习,一起成长习

相似文章

    10连胜?廖筐是尘土飞扬!CCTV5做出了正确的决定,郭艾伦做出了回应

    本赛季,辽宁男子篮球队凭借他的出色表现,连胜场次已经达到场。他们不仅在联赛第一阶段就赢得了所有冠军,而且在主要统计排名中也进入了前六名。廖篮他在场均得分 篮板 盖帽 抢断 助攻等方面表现出了很强的统治力。而更令人震惊的是,它竟然还在郭亚伦在团队缺席的情况下取得的成果。郭亚伦如廖篮核心球员回归后,无疑...

    印度的经济增长正在上升,但它可能是美元的第一个目标

    年全球前三季度经济数据出炉,其中印度经济增长无与伦比,成为世界主要国家中增长最快的国家。印度统计局公布的数据显示,年前三季度,印度全社会完成的名义GDP初步统计结果为与去年同期相比,在排除所有商品和服务 后,实现了亿卢比 实现了实际增长 高于世界银行的 印度经济占世界GDP的 目前正处于快速发展阶段...

    《重返南海废墟》陈穆池的古猜测无与伦比,我真诚不矫揉造作!

    重返南海废墟 上映已经很多天了,因为题材 平台 观众 特效有限,所以不算大爆。不过,陈牧池饰演的顾柴虽然只是群演,却是出圈,而与 重返南海废墟 的热点话题有关,顾柴已经获得了超过万的观看量,, 次讨论。古柴是美男鱼的真锤 古柴海底捞必备品 等话题受到了大量阅读和关注。一开始,平台并没有带来陈沐池的古...

    一加 Ace Pro 顶级处理器性能高,运行流畅,仅需 2299 元!

    大家好,今天给大家介绍一款备受期待的大促销手机 OnePlus Ace Pro!不得不说,这款手机的配置真的是让人兴奋不已,拥有顶级的处理器,高性能流畅的运行,让人无法抗拒 想要体验顶级性能,一定不能错过这款手机,现在只需元即可买到!是不是物有所值?一起来看看OnePlus Ace Pro的亮点吧!...

    1 4313是一种高强度、高耐腐蚀的不锈钢材料百科全书

    是一种高强度 高耐腐蚀的不锈钢材料。.是一种不锈钢材料,具有优良的机械性能和耐腐蚀性。强度高,能承受较大的压力和应力,耐腐蚀性好,可在各种腐蚀性环境中长期使用。这种不锈钢材料广泛应用于各种工业领域,如石油化工 海洋工程 医疗设备等。.不锈钢材料的强度和耐腐蚀性主要归功于其化学成分。它含有高铬元素,能...