<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Shawn.Yang on Medium]]></title>
        <description><![CDATA[Stories by Shawn.Yang on Medium]]></description>
        <link>https://medium.com/@shawn.ck.yang?source=rss-c54c340fa1bb------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*j1iKBEf-fYVFr46Xp9jPsw.jpeg</url>
            <title>Stories by Shawn.Yang on Medium</title>
            <link>https://medium.com/@shawn.ck.yang?source=rss-c54c340fa1bb------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 23 Jun 2026 17:27:05 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shawn.ck.yang/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Apache Fory Serialization 1.0 Released Now]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fory-serialization-1-0-released-now-b1c4a76f397d?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/b1c4a76f397d</guid>
            <category><![CDATA[serialization]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[big-data]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Thu, 28 May 2026 13:02:20 GMT</pubDate>
            <atom:updated>2026-05-28T13:04:56.860Z</atom:updated>
            <content:encoded><![CDATA[<p>I’m excited to announce the Apache Fory Serialization Framework 1.0.0 release. This milestone release includes <a href="https://github.com/apache/fory/compare/v0.17.0...v1.0.0">84 PRs</a> from 11 distinct contributors and turns the cross-language runtime into the default path across supported languages. See the <a href="https://fory.apache.org/docs/start/install">Install</a> page to get the libraries for your platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TmZVhkCEJllezwDYEuvfpA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5EfTyRA9z5gvCcEh69b6ug.png" /></figure><h3>Highlights</h3><p>Apache Fory 1.0.0 standardizes the cross-language serialization model. The unified xlang type system is now the default mode across languages, with compatible-mode reads, simplified field ordering, and better list/array compatibility. The release also adds decimal and bfloat16 support for xlang serialization.</p><p>The language runtimes continue to converge around the same schema and metadata model. Nested container and field codec support landed across Rust, C++, C#, Go, Dart, Python, and Swift. Kotlin gains xlang, KSP, and schema IDL support, while Scala adds schema IDL support and updated generated annotations.</p><p>This release also expands deployment coverage and performance work. Java gains Android serialization support, annotation processor support, schema typed row field accessors, and nested type-use serialization metadata. Dart typed-container fast paths and generated struct optimizations improve throughput, alongside refreshed benchmark plots.</p><p>Key Features:</p><ul><li>Unified xlang type system and default xlang mode: <a href="https://github.com/apache/fory/pull/3644">https://github.com/apache/fory/pull/3644</a>, <a href="https://github.com/apache/fory/pull/3685">https://github.com/apache/fory/pull/3685</a></li><li>Decimal and bfloat16 support for xlang serialization: <a href="https://github.com/apache/fory/pull/3599">https://github.com/apache/fory/pull/3599</a>, <a href="https://github.com/apache/fory/pull/3605">https://github.com/apache/fory/pull/3605</a></li><li>Nested container and field codec support: <a href="https://github.com/apache/fory/pull/3625">https://github.com/apache/fory/pull/3625</a>, <a href="https://github.com/apache/fory/pull/3630">https://github.com/apache/fory/pull/3630</a>, <a href="https://github.com/apache/fory/pull/3636">https://github.com/apache/fory/pull/3636</a>, <a href="https://github.com/apache/fory/pull/3639">https://github.com/apache/fory/pull/3639</a>, <a href="https://github.com/apache/fory/pull/3640">https://github.com/apache/fory/pull/3640</a>, <a href="https://github.com/apache/fory/pull/3641">https://github.com/apache/fory/pull/3641</a>, <a href="https://github.com/apache/fory/pull/3643">https://github.com/apache/fory/pull/3643</a></li><li>Kotlin xlang, KSP, and schema IDL support: <a href="https://github.com/apache/fory/pull/3679">https://github.com/apache/fory/pull/3679</a>, <a href="https://github.com/apache/fory/pull/3684">https://github.com/apache/fory/pull/3684</a></li><li>Scala schema IDL support and generated annotation updates: <a href="https://github.com/apache/fory/pull/3681">https://github.com/apache/fory/pull/3681</a>, <a href="https://github.com/apache/fory/pull/3682">https://github.com/apache/fory/pull/3682</a></li><li>Android serialization and Java annotation processor support: <a href="https://github.com/apache/fory/pull/3667">https://github.com/apache/fory/pull/3667</a>, <a href="https://github.com/apache/fory/pull/3670">https://github.com/apache/fory/pull/3670</a></li><li>Xlang compatible-mode improvements: <a href="https://github.com/apache/fory/pull/3648">https://github.com/apache/fory/pull/3648</a>, <a href="https://github.com/apache/fory/pull/3650">https://github.com/apache/fory/pull/3650</a>, <a href="https://github.com/apache/fory/pull/3675">https://github.com/apache/fory/pull/3675</a></li><li>Serialization performance improvements: <a href="https://github.com/apache/fory/pull/3609">https://github.com/apache/fory/pull/3609</a>, <a href="https://github.com/apache/fory/pull/3653">https://github.com/apache/fory/pull/3653</a>, <a href="https://github.com/apache/fory/pull/3656">https://github.com/apache/fory/pull/3656</a>, <a href="https://github.com/apache/fory/pull/3661">https://github.com/apache/fory/pull/3661</a></li><li>Java row accessors and nested type-use metadata: <a href="https://github.com/apache/fory/pull/3631">https://github.com/apache/fory/pull/3631</a>, <a href="https://github.com/apache/fory/pull/3633">https://github.com/apache/fory/pull/3633</a></li></ul><h3>Features</h3><ul><li>feat(ci): fix release for csharp and dart by @chaokunyang in <a href="https://github.com/apache/fory/pull/3582">https://github.com/apache/fory/pull/3582</a></li><li>feat(rust): add configurable size guardrails by @ayush00git in <a href="https://github.com/apache/fory/pull/3579">https://github.com/apache/fory/pull/3579</a></li><li>refactor(rust): move Fory configuration to builder by @chaokunyang in <a href="https://github.com/apache/fory/pull/3593">https://github.com/apache/fory/pull/3593</a></li><li>feat(xlang): add decimal and align serializers for xlang by @chaokunyang in <a href="https://github.com/apache/fory/pull/3599">https://github.com/apache/fory/pull/3599</a></li><li>refactor(dart): aligned dart internal implementation by @Geethapranay1 in <a href="https://github.com/apache/fory/pull/3601">https://github.com/apache/fory/pull/3601</a></li><li>feat(xlang): add bfloat16 support by @chaokunyang in <a href="https://github.com/apache/fory/pull/3605">https://github.com/apache/fory/pull/3605</a></li><li>feat(dart): support dart web platform by @chaokunyang in <a href="https://github.com/apache/fory/pull/3608">https://github.com/apache/fory/pull/3608</a></li><li>perf(dart): typed-container write fast path with scan elimination by @yash-agarwa-l in <a href="https://github.com/apache/fory/pull/3609">https://github.com/apache/fory/pull/3609</a></li><li>feat(swift): nested container override support for swift by @chaokunyang in <a href="https://github.com/apache/fory/pull/3625">https://github.com/apache/fory/pull/3625</a></li><li>feat(java): add schema typed row fields accessor by @chaokunyang in <a href="https://github.com/apache/fory/pull/3631">https://github.com/apache/fory/pull/3631</a></li><li>feat: add nested container codec for rust by @chaokunyang in <a href="https://github.com/apache/fory/pull/3630">https://github.com/apache/fory/pull/3630</a></li><li>feat(java): support nested type-use serialization metadata by @chaokunyang in <a href="https://github.com/apache/fory/pull/3633">https://github.com/apache/fory/pull/3633</a></li><li>refactor(cpp): remove abseil dependency by @chaokunyang in <a href="https://github.com/apache/fory/pull/3634">https://github.com/apache/fory/pull/3634</a></li><li>feat(cpp): add nested field codec support by @chaokunyang in <a href="https://github.com/apache/fory/pull/3636">https://github.com/apache/fory/pull/3636</a></li><li>feat(csharp): support nested container field codec by @chaokunyang in <a href="https://github.com/apache/fory/pull/3639">https://github.com/apache/fory/pull/3639</a></li><li>feat(go): support nested field annotation type specs by @chaokunyang in <a href="https://github.com/apache/fory/pull/3640">https://github.com/apache/fory/pull/3640</a></li><li>feat(dart): support nested container field codec for dart by @chaokunyang in <a href="https://github.com/apache/fory/pull/3641">https://github.com/apache/fory/pull/3641</a></li><li>feat(python): support nested field schema encodings by @chaokunyang in <a href="https://github.com/apache/fory/pull/3643">https://github.com/apache/fory/pull/3643</a></li><li>feat(xlang): unified xlang type system by @chaokunyang in <a href="https://github.com/apache/fory/pull/3644">https://github.com/apache/fory/pull/3644</a></li><li>feat(xlang): add comprehensive read checks by @chaokunyang in <a href="https://github.com/apache/fory/pull/3647">https://github.com/apache/fory/pull/3647</a></li><li>feat(xlang): use compatible for xlang by default by @chaokunyang in <a href="https://github.com/apache/fory/pull/3648">https://github.com/apache/fory/pull/3648</a></li><li>feat(xlang): compatible read between list array field by @chaokunyang in <a href="https://github.com/apache/fory/pull/3650">https://github.com/apache/fory/pull/3650</a></li><li>perf(dart): remove generated struct slot bridge by @chaokunyang in <a href="https://github.com/apache/fory/pull/3653">https://github.com/apache/fory/pull/3653</a></li><li>perf: optimize serialization perf by @chaokunyang in <a href="https://github.com/apache/fory/pull/3656">https://github.com/apache/fory/pull/3656</a></li><li>perf: update benchmark plots by @chaokunyang in <a href="https://github.com/apache/fory/pull/3661">https://github.com/apache/fory/pull/3661</a></li><li>refactor(rust): use absolute path in generated Rust code by @BaldDemian in <a href="https://github.com/apache/fory/pull/3666">https://github.com/apache/fory/pull/3666</a></li><li>feat: add android support by @chaokunyang in <a href="https://github.com/apache/fory/pull/3667">https://github.com/apache/fory/pull/3667</a></li><li>feat(compiler): add helpers to generate unified gRPC service/method names by @BaldDemian in <a href="https://github.com/apache/fory/pull/3672">https://github.com/apache/fory/pull/3672</a></li><li>feat(java): annotation processor for android serialization by @chaokunyang in <a href="https://github.com/apache/fory/pull/3670">https://github.com/apache/fory/pull/3670</a></li><li>feat(xlang): simplify xlang field ordering by @chaokunyang in <a href="https://github.com/apache/fory/pull/3675">https://github.com/apache/fory/pull/3675</a></li><li>feat(kotlin): add kotlin xlang and ksp support by @chaokunyang in <a href="https://github.com/apache/fory/pull/3679">https://github.com/apache/fory/pull/3679</a></li><li>refactor(java): replace static serializer spi lookup by @chaokunyang in <a href="https://github.com/apache/fory/pull/3680">https://github.com/apache/fory/pull/3680</a></li><li>feat(scala): add scala schema idl support by @chaokunyang in <a href="https://github.com/apache/fory/pull/3681">https://github.com/apache/fory/pull/3681</a></li><li>feat(scala): update generated annotation by @chaokunyang in <a href="https://github.com/apache/fory/pull/3682">https://github.com/apache/fory/pull/3682</a></li><li>feat(rust): make rust chrono optional by @chaokunyang in <a href="https://github.com/apache/fory/pull/3683">https://github.com/apache/fory/pull/3683</a></li><li>feat(kotlin): add schema idl support to kotlin by @chaokunyang in <a href="https://github.com/apache/fory/pull/3684">https://github.com/apache/fory/pull/3684</a></li><li>feat(xlang): use xlang as default mode for all languages by @chaokunyang in <a href="https://github.com/apache/fory/pull/3685">https://github.com/apache/fory/pull/3685</a></li></ul><h3>Bug Fixes</h3><ul><li>fix(dart): resolve fory pub.dev score issues by @chaokunyang in <a href="https://github.com/apache/fory/pull/3585">https://github.com/apache/fory/pull/3585</a></li><li>fix(dart): fix dart ci by @chaokunyang in <a href="https://github.com/apache/fory/pull/3586">https://github.com/apache/fory/pull/3586</a></li><li>fix(dart): use getUint32 for correctly encoding u64 value by @ayush00git in <a href="https://github.com/apache/fory/pull/3592">https://github.com/apache/fory/pull/3592</a></li><li>fix(c++): fix c++ duration serialization by @chaokunyang in <a href="https://github.com/apache/fory/pull/3598">https://github.com/apache/fory/pull/3598</a></li><li>fix(javascript): align TypeMeta preamble constants with python/java/rust/go xlang bindings by @emrul in <a href="https://github.com/apache/fory/pull/3603">https://github.com/apache/fory/pull/3603</a></li><li>fix(javascript): fix javascript schema idl tests by @chaokunyang in <a href="https://github.com/apache/fory/pull/3604">https://github.com/apache/fory/pull/3604</a></li><li>fix(dart): added &gt;&gt;&gt; for correct logical right shift semantics in uint by @ayush00git in <a href="https://github.com/apache/fory/pull/3607">https://github.com/apache/fory/pull/3607</a></li><li>fix(go): ensure physical buffer space for unsafe varint fast-paths by @ayush00git in <a href="https://github.com/apache/fory/pull/3613">https://github.com/apache/fory/pull/3613</a></li><li>fix(go): add bound checking for refResolver and metaStringResolver reads by @ayush00git in <a href="https://github.com/apache/fory/pull/3615">https://github.com/apache/fory/pull/3615</a></li><li>fix(go): added pre-allocation bounds checks for slices and strings by @ayush00git in <a href="https://github.com/apache/fory/pull/3618">https://github.com/apache/fory/pull/3618</a></li><li>fix(go): added maxBinarySize limit to decimal deserialization by @ayush00git in <a href="https://github.com/apache/fory/pull/3623">https://github.com/apache/fory/pull/3623</a></li><li>fix(go): add configurable fieldCount and fieldDepth guardrails by @ayush00git in <a href="https://github.com/apache/fory/pull/3620">https://github.com/apache/fory/pull/3620</a></li><li>fix(java): honor record field encoding in generated decode by @mandrean in <a href="https://github.com/apache/fory/pull/3626">https://github.com/apache/fory/pull/3626</a></li><li>fix(java): preserve externalizable containers in compatible mode by @mandrean in <a href="https://github.com/apache/fory/pull/3628">https://github.com/apache/fory/pull/3628</a></li><li>fix(python): enforce more checks in read by @chaokunyang in <a href="https://github.com/apache/fory/pull/3632">https://github.com/apache/fory/pull/3632</a></li><li>fix(xlang): fix xlang type system by @chaokunyang in <a href="https://github.com/apache/fory/pull/3646">https://github.com/apache/fory/pull/3646</a></li><li>fix(java): use REPLACE_STUB_ID for unregistered writeReplace classes to prevent cross-JVM ClassNotFoundException by @wakilurislam in <a href="https://github.com/apache/fory/pull/3638">https://github.com/apache/fory/pull/3638</a></li><li>fix(java): fix set view ref tracking by @chaokunyang in <a href="https://github.com/apache/fory/pull/3649">https://github.com/apache/fory/pull/3649</a></li><li>fix(java): recover map declared serializers for compatible reads by @mandrean in <a href="https://github.com/apache/fory/pull/3654">https://github.com/apache/fory/pull/3654</a></li><li>fix: include TypeMeta header bits in hash by @chaokunyang in <a href="https://github.com/apache/fory/pull/3659">https://github.com/apache/fory/pull/3659</a></li><li>fix(java): serialize suppressed exceptions by @chaokunyang in <a href="https://github.com/apache/fory/pull/3663">https://github.com/apache/fory/pull/3663</a></li><li>fix(javascript): preserve getTypeInfo in regenerated read serializer by @xhzq233 in <a href="https://github.com/apache/fory/pull/3669">https://github.com/apache/fory/pull/3669</a></li><li>fix(java): validate subclass serializer layer counts by @chaokunyang in <a href="https://github.com/apache/fory/pull/3676">https://github.com/apache/fory/pull/3676</a></li><li>fix(java): avoid instantiating abstract meta-share types by @chaokunyang in <a href="https://github.com/apache/fory/pull/3677">https://github.com/apache/fory/pull/3677</a></li><li>fix: fix release script by @chaokunyang in <a href="https://github.com/apache/fory/pull/3687">https://github.com/apache/fory/pull/3687</a></li></ul><h3>Other Improvements</h3><ul><li>chore: skip auto release for tag starts with go by @chaokunyang in <a href="https://github.com/apache/fory/pull/3584">https://github.com/apache/fory/pull/3584</a></li><li>docs: add NuGet badge by @chaokunyang in <a href="https://github.com/apache/fory/pull/3587">https://github.com/apache/fory/pull/3587</a></li><li>docs(java): update graalvm guide location by @chaokunyang in <a href="https://github.com/apache/fory/pull/3588">https://github.com/apache/fory/pull/3588</a></li><li>docs: rename graalvm_support.md to graalvm-support.md by @chaokunyang in <a href="https://github.com/apache/fory/pull/3589">https://github.com/apache/fory/pull/3589</a></li><li>chore(rust): refine varint read/write method name by @chaokunyang in <a href="https://github.com/apache/fory/pull/3590">https://github.com/apache/fory/pull/3590</a></li><li>docs: move development guide to docs root by @chaokunyang in <a href="https://github.com/apache/fory/pull/3591">https://github.com/apache/fory/pull/3591</a></li><li>chore(dart): add missing license headers by @chaokunyang in <a href="https://github.com/apache/fory/pull/3594">https://github.com/apache/fory/pull/3594</a></li><li>chore(csharp): add more csharp and swift tests by @chaokunyang in <a href="https://github.com/apache/fory/pull/3597">https://github.com/apache/fory/pull/3597</a></li><li>chore(dart): refine dart xlang serialization by @chaokunyang in <a href="https://github.com/apache/fory/pull/3596">https://github.com/apache/fory/pull/3596</a></li><li>docs: add more agent harness rules by @chaokunyang in <a href="https://github.com/apache/fory/pull/3610">https://github.com/apache/fory/pull/3610</a></li><li>chore(dart): remove stale dart note files by @chaokunyang in <a href="https://github.com/apache/fory/pull/3642">https://github.com/apache/fory/pull/3642</a></li><li>chore(java): configure default Fory log level by @chaokunyang in <a href="https://github.com/apache/fory/pull/3657">https://github.com/apache/fory/pull/3657</a></li><li>chore: clean up code and add compiler warning checks by @chaokunyang in <a href="https://github.com/apache/fory/pull/3660">https://github.com/apache/fory/pull/3660</a></li><li>docs: tighten benchmark throughput plots by @chaokunyang in <a href="https://github.com/apache/fory/pull/3662">https://github.com/apache/fory/pull/3662</a></li><li>docs: update readme by @chaokunyang in <a href="https://github.com/apache/fory/pull/3664">https://github.com/apache/fory/pull/3664</a></li><li>docs: add README schema IDL example by @chaokunyang in <a href="https://github.com/apache/fory/pull/3665">https://github.com/apache/fory/pull/3665</a></li><li>docs: update xlang/native serialization doc by @chaokunyang in <a href="https://github.com/apache/fory/pull/3686">https://github.com/apache/fory/pull/3686</a></li></ul><h3>New Contributors</h3><ul><li>@emrul made their first contribution in <a href="https://github.com/apache/fory/pull/3603">https://github.com/apache/fory/pull/3603</a></li><li>@wakilurislam made their first contribution in <a href="https://github.com/apache/fory/pull/3638">https://github.com/apache/fory/pull/3638</a></li><li>@xhzq233 made their first contribution in <a href="https://github.com/apache/fory/pull/3669">https://github.com/apache/fory/pull/3669</a></li></ul><p><strong>Full Changelog</strong>: <a href="https://github.com/apache/fory/compare/v0.17.0...v1.0.0">https://github.com/apache/fory/compare/v0.17.0...v1.0.0</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b1c4a76f397d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Extend Protobuf/FlatBuffers Schema IDL with Shared/Circular Reference Support]]></title>
            <link>https://medium.com/@shawn.ck.yang/extend-protobuf-flatbuffers-schema-idl-with-shared-circular-reference-support-af4ec3637231?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/af4ec3637231</guid>
            <category><![CDATA[infrastructure]]></category>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[big-data]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Tue, 17 Mar 2026 02:58:59 GMT</pubDate>
            <atom:updated>2026-03-17T02:58:59.027Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR</strong>: If you already have .proto or .fbs schemas and you want shared/circular reference support, with the Fory compiler you can keep those schemas, add a small set of Fory options, then foryc generates idiomatic native models across Fory-supported languages, so you can serialize object graphs without manual *_id link reconstruction or rewriting your entire schema into Fory Schema.</p><ul><li>GitHub: <a href="https://github.com/apache/fory">https://github.com/apache/fory</a></li><li>Compiler docs: <a href="https://fory.apache.org/docs/compiler">https://fory.apache.org/docs/compiler</a></li><li>Install: pip install fory-compiler</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ka7HEVUMQFkfZr7o.png" /></figure><h3>The Gap in Protobuf and FlatBuffers Schemas</h3><p>Many production models are object graphs, not pure value trees:</p><ul><li>Parent pointers (child.parent)</li><li>Shared nodes (two edges pointing to the same object)</li><li>Cycles (A -&gt; B -&gt; A)</li></ul><p>In plain protobuf or FlatBuffers schema design, these relationships are usually represented indirectly with manual ID links (parent_id, child_ids) and rebuilt in application code after decode.</p><p>Apache Fory adds schema-level reference tracking so these graph semantics can be declared directly in protobuf/FlatBuffers source via Fory options.</p><h3>Keep .proto and .fbs, Add Graph Semantics</h3><p>You do not need to rewrite everything into .fdl first.</p><ul><li>For protobuf input, use (fory).ref, (fory).weak_ref, and related options.</li><li>For FlatBuffers input, use fory_ref:true, fory_weak_ref:true, and related attributes.</li><li>Compile with foryc.</li><li>Get Fory-generated models and Fory wire format.</li></ul><p>Important: this path reuses schema syntax and structure, but serialization output is Fory binary protocol, not protobuf/FlatBuffers wire compatibility.</p><h3>Protobuf: From ID Workarounds to ref</h3><h3>Protobuf-style workaround (value-tree oriented)</h3><pre>message TreeNode {<br>  string id = 1;<br>  string parent_id = 2;<br>  repeated string child_ids = 3;<br>}</pre><h3>Protobuf + Fory options (graph semantics)</h3><pre>syntax = &quot;proto3&quot;;<br>message TreeNode {<br>  TreeNode parent = 1 [(fory).weak_ref = true];<br>  repeated TreeNode children = 2 [(fory).ref = true];<br>}</pre><p>What this means:</p><ul><li>weak_ref = true implies ref tracking and generates weak-pointer semantics where relevant (for example C++/Rust).</li><li>For repeated fields, (fory).ref = true applies to list elements.</li><li>For map&lt;K, V&gt;, (fory).ref = true applies to map values.</li></ul><p>You can also tune Rust pointer flavor:</p><pre>message Graph {<br>  Node root = 1 [(fory).ref = true, (fory).thread_safe_pointer = false];<br>}</pre><h3>FlatBuffers: Add fory_ref Attributes</h3><h3>FlatBuffers schema with Fory reference attributes</h3><pre>namespace demo;<br>table Node {<br>  parent: Node (fory_weak_ref: true);<br>  children: [Node] (fory_ref: true);<br>  cached: Node (fory_ref: true, fory_thread_safe_pointer: false);<br>}</pre><p>Semantics:</p><ul><li>fory_weak_ref:true implies reference tracking.</li><li>fory_thread_safe_pointer affects pointer flavor on ref-tracked fields.</li><li>For list fields, fory_ref:true applies to elements.</li></ul><p>FlatBuffers input is translated into Fory IR, then normal Fory codegen runs. The generated API surface is native objects (not FlatBuffers ByteBuffer-wrapper APIs).</p><h3>Inspect Before You Commit</h3><p>You can inspect how .proto or .fbs is translated:</p><pre># Protobuf to translated Fory schema<br>foryc schema.proto --emit-fdl<br># FlatBuffers to translated Fory schema<br>foryc schema.fbs --emit-fdl --emit-fdl-path ./translated</pre><p>Then generate code:</p><pre>foryc schema.proto \<br>  --java_out=./java/gen \<br>  --python_out=./python/gen \<br>  --go_out=./go/gen \<br>  --rust_out=./rust/gen \<br>  --cpp_out=./cpp/gen</pre><p>This is the migration-friendly loop:</p><ol><li>Keep existing schema files.</li><li>Add only Fory reference options where graph semantics are required.</li><li>Inspect translated .fdl.</li><li>Generate and run roundtrip tests.</li></ol><h3>What You Get After Generation</h3><p>With Fory codegen, you get native language models and reference-aware serialization behavior:</p><ul><li>Java: POJOs/records with Fory metadata</li><li>Python: dataclasses + registration helpers</li><li>Go: structs with tags</li><li>Rust: native structs with ref-pointer mapping</li><li>C++: native classes/structs with shared/weak pointer mapping</li><li>C#, Swift, and more: idiomatic generated models</li></ul><p>For object-graph-heavy workflows, this removes a common layer of manual ID-link hydration code.</p><h3>Behavioral Boundaries to Keep in Mind</h3><ol><li>This is not protobuf or FlatBuffers wire compatibility. The schema frontend is reused, but bytes on the wire are Fory protocol.</li><li>Protobuf unknown-field behavior is different. Protobuf preserves unknown fields; Fory does not preserve protobuf unknown-field payloads.</li><li>Reference tracking should be explicit and minimal. Use ref/weak_ref for true shared/cyclic parts of the graph, not for all fields.</li></ol><h3>Practical Migration Pattern</h3><p>If you already run protobuf or FlatBuffers in production:</p><ol><li>Keep package/namespace names stable.</li><li>Add Fory reference options only to graph-shaped fields.</li><li>Generate code with foryc and run roundtrip tests.</li><li>Migrate internal object-heavy paths first.</li><li>Keep external protobuf/gRPC boundaries as-is when needed.</li></ol><p>This lets you adopt graph semantics incrementally without a full schema rewrite.</p><h3>Conclusion</h3><p>Protobuf and FlatBuffers schema files can be a starting point for Fory graph-aware serialization, not a blocker.</p><p>By adding a small set of Fory extension options (ref, weak_ref, pointer-style hints), you can express shared identity and circular links directly in existing .proto/.fbs sources, generate native models, and remove manual object-link reconstruction code in object-graph-heavy systems.</p><p>If your data model is a graph, make that graph explicit in the schema.</p><p><strong>Get started:</strong></p><pre>pip install fory-compiler<br>foryc --help</pre><p><strong>References:</strong></p><ul><li>Object-graph Schema IDL reference article: <a href="https://fory.apache.org/blog/fory_schema_idl_for_object_graph">https://fory.apache.org/blog/fory_schema_idl_for_object_graph</a></li><li>Protobuf IDL support: <a href="https://fory.apache.org/docs/compiler/protobuf_idl_support">https://fory.apache.org/docs/compiler/protobuf_idl_support</a></li><li>FlatBuffers IDL support: <a href="https://fory.apache.org/docs/compiler/flatbuffers_idl">https://fory.apache.org/docs/compiler/flatbuffers_idl</a></li><li>Schema syntax (ref, optional, union): <a href="https://fory.apache.org/docs/compiler/syntax">https://fory.apache.org/docs/compiler/syntax</a></li><li>Generated code overview: <a href="https://fory.apache.org/docs/compiler/generated_code">https://fory.apache.org/docs/compiler/generated_code</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=af4ec3637231" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache Fory™ Schema IDL: Serialization IDL for Object Graphs and Generated API Ergonomics]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fory-schema-idl-serialization-idl-for-object-graphs-and-generated-api-ergonomics-00b8ffbd30d3?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/00b8ffbd30d3</guid>
            <category><![CDATA[microservices]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[networking]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Thu, 12 Mar 2026 06:04:10 GMT</pubDate>
            <atom:updated>2026-03-12T06:04:10.791Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR</strong>: Apache Fory Schema IDL is the first cross-language serialization IDL for <strong>object graphs serialization</strong>. Define your types once in a .fdl file, and the compiler generates idiomatic domain objects for <strong>Java, Python, Go, Rust, C++, C#, Swift, and more</strong> — with shared refs, cycles, polymorphism, schema evolution, and optional types built into the schema model.</p><ul><li>GitHub: <a href="https://github.com/apache/fory">https://github.com/apache/fory</a></li><li>Docs: <a href="https://fory.apache.org/docs/compiler">https://fory.apache.org/docs/compiler</a></li><li>Install: pip install fory-compiler</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*cULsbui2AKJ9IpUW.png" /></figure><h3>The Object Graph Gap</h3><p>Most existing serialization IDLs model data as value trees: flat messages with no schema-level notion of shared identity, cycles, or reusable standalone polymorphic types. When the actual data is a graph, that gap usually shows up in three places:</p><ol><li><strong>Shared and Circular References</strong>: If two fields refer to the same logical object, Protocol Buffers and FlatBuffers do not preserve that shared identity in the schema or on the wire. Parent pointers, DAGs, and cycles have no schema-level representation, so they fall back to manual ID fields and application-side reconstruction.</li><li><strong>Polymorphism</strong>: Protobuf oneof and FlatBuffers union are inline alternatives embedded in an enclosing message, not reusable standalone schema types. Protobuf Any supports open-ended polymorphism, but only for messages and via a type URL. FlatBuffers has no equivalent.</li><li><strong>Generated Types as Domain Models</strong>: FlatBuffers APIs are primarily buffer-access wrappers. Protobuf generates transport-first types in many languages, so users often add a conversion layer to get back to idiomatic domain objects. The schema defines the wire format, but not the application model.</li></ol><p>Apache Fory Schema IDL closes that gap.</p><h3>What Makes Fory IDL Different?</h3><p>Apache Fory Schema IDL is built around object graphs as a first-class concept. You define your types once — including shared references, circular structures, standalone unions, and polymorphic fields — run the compiler, and get idiomatic code in every supported language on top of the same Fory wire format.</p><p>In this article, “serialization IDL for object graphs” means the schema itself can describe shared identity, cycles, and reusable polymorphic types directly, instead of forcing users to flatten everything into value trees and rebuild links with manual IDs or application-side conventions later.</p><p>That shows up in three places:</p><ul><li>ref makes shared references and cycles part of the schema contract.</li><li>union and any make polymorphism a reusable schema feature rather than only an inline transport detail.</li><li>The generated code stays usable as host-language application models instead of wrapper types that require another conversion layer.</li></ul><p>The sections below show how that works in practice.</p><h3>First-Class Shared References</h3><p>Fory IDL has a ref modifier that makes shared and circular reference tracking explicit in the schema:</p><pre>message TreeNode {<br>    string value = 1;<br>    ref TreeNode parent = 2;          // Shared reference — can point back<br>    list&lt;ref TreeNode&gt; children = 3;  // Each child is reference-tracked<br>}</pre><p>When you serialize a tree where children point back to their parent, Fory encodes each object exactly once and uses back-references for duplicates. No manual ID-link fields. No application-level reconstruction logic. The object graph contract lives in the schema itself.</p><p>For parent pointers where you want to break ownership cycles, ref(weak=true) generates weak pointer types (e.g., ArcWeak&lt;Node&gt; in Rust, std::weak_ptr in C++).</p><h3>Idiomatic Domain Objects, Not Wrappers</h3><p>A key difference from Protocol Buffers and FlatBuffers is that compiling a Fory .fdl schema produces host-language models you can use directly:</p><ul><li><strong>Java</strong>: Plain POJOs with @ForyField annotations — usable directly in Spring, Hibernate, or any framework</li><li><strong>Python</strong>: @dataclass types with standard type hints</li><li><strong>Go</strong>: Structs with fory:&quot;id=...&quot; struct tags</li><li><strong>Rust</strong>: Structs with #[derive(ForyObject)]</li><li><strong>C++</strong>: final classes with FORY_STRUCT macros — zero runtime reflection</li><li><strong>C#</strong>: Classes with [ForyObject] attributes</li><li><strong>Swift</strong>: @ForyObject models with @ForyField metadata</li></ul><p>In many applications, no adapter layer is needed. The generated types can be used directly as your domain objects.</p><h3>Built-In Unions (Sum Types)</h3><p>Fory IDL has a first-class union construct that maps to the most idiomatic sum type in each language:</p><pre>message Dog {<br>    string name = 1;<br>    int32 bark_volume = 2;<br>}<br>message Cat {<br>    string name = 1;<br>    int32 lives = 2;<br>}<br>union Animal {<br>    Dog dog = 1;<br>    Cat cat = 2;<br>}</pre><p>This generates:</p><ul><li><strong>Rust</strong>: enum Animal { Dog(Dog), Cat(Cat) }</li><li><strong>C++</strong>: std::variant-based wrapper with is_dog(), as_dog(), visit() APIs</li><li><strong>Swift</strong>: Tagged enum with associated values</li><li><strong>Java</strong>: Union subclass with typed case accessors</li><li><strong>Python</strong>: Union subclass with is_dog() / dog_value() helpers</li><li><strong>Go</strong>: Typed case struct with AsDog() / visitor pattern</li><li><strong>C#</strong>: Union subclass with IsDog / DogValue() helpers</li></ul><p>Every language gets the same semantics, but expressed in each language’s idiom.</p><h3>Polymorphic Fields with any</h3><p>Sometimes you don’t know the concrete type of a field at schema-definition time. An event bus carries heterogeneous payloads. A plugin system accepts user-defined message types. Fory IDL’s any type handles this — it writes the runtime type identity into the binary stream and resolves it on the other side:</p><pre>message Envelope {<br>    string event_type = 1;<br>    any payload = 2;          // Carries dynamic values supported by Fory<br>}</pre><p>At runtime, payload can hold dynamic values supported by Fory — other generated messages, built-in scalars, or collection types. The serialized bytes include runtime type metadata, so the deserializer can reconstruct the concrete value on the other side:</p><p>LanguageGenerated Field TypeJavaObject payloadPythonpayload: AnyGoPayload anyRustpayload: Box&lt;dyn Any&gt;C++std::any payloadC#object PayloadSwiftvar payload: Any</p><p>This gives you protobuf Any-like flexibility, but in the generated Fory model and without requiring protobuf-style type URLs in the schema surface.</p><p>The three features above — ref, union/any, and idiomatic generated code — make Fory IDL an object-graph-first schema language. Schema evolution is a separate concern, but it completes the production story:</p><h3>Schema Evolution Out of the Box</h3><p>Add fields, remove fields, deploy independently. In compatible mode, fields are matched by field id, missing fields get defaults, and unknown fields are skipped:</p><pre>// Version 1 — deployed to production<br>message User {<br>    string name = 1;<br>    int32 age = 2;<br>}<br>// Version 2 - new field added by another team<br>message User {<br>    string name = 1;<br>    int32 age = 2;<br>    optional string email = 3;  // New: safely ignored by V1 consumers<br>}</pre><p>This still follows compatibility rules; it is not a license for arbitrary schema changes. But for normal additive and removal changes, you do not need coordinated big-bang deployments or a separate version-negotiation layer.</p><h3>A Complete Walkthrough</h3><p>Let’s build a realistic e-commerce schema, see it work across current Fory-supported languages, and then make the object-graph part explicit with a shared-customer round trip.</p><h3>1. Define the Schema</h3><p>Create ecommerce.fdl:</p><pre>package ecommerce;<br>enum OrderStatus {<br>    PENDING = 0;<br>    CONFIRMED = 1;<br>    SHIPPED = 2;<br>    DELIVERED = 3;<br>}<br>message Address {<br>    string street = 1;<br>    string city = 2;<br>    string country = 3;<br>}<br>message Customer {<br>    string id = 1;<br>    string name = 2;<br>    optional string email = 3;<br>    optional Address address = 4;<br>}<br>message OrderItem {<br>    string sku = 1;<br>    int32 quantity = 2;<br>    float64 unit_price = 3;<br>}<br>message Order {<br>    string order_id = 1;<br>    ref Customer customer = 2;<br>    list&lt;OrderItem&gt; items = 3;<br>    OrderStatus status = 4;<br>    float64 total = 5;<br>    optional string notes = 6;<br>    timestamp created_at = 7;<br>}<br>message OrderBatch {<br>    list&lt;Order&gt; orders = 1;<br>}</pre><h3>2. Install the Compiler and Generate Code</h3><pre>pip install fory-compiler<br># Generate code for all currently supported Fory IDL languages in one command<br>foryc ecommerce.fdl \<br>  --java_out=./java/src/main/java \<br>  --python_out=./python/gen \<br>  --go_out=./go/gen \<br>  --rust_out=./rust/gen \<br>  --cpp_out=./cpp/gen \<br>  --csharp_out=./csharp/gen \<br>  --swift_out=./swift/gen</pre><p>A single command can generate code for multiple languages. Registration helpers, byte helpers, and type IDs are generated automatically.</p><h3>3. Use the Generated Code</h3><p><strong>Java</strong> — serialize an order:</p><pre>import ecommerce.*;<br>Order order = new Order();<br>order.setOrderId(&quot;ORD-2026-001&quot;);<br>Customer customer = new Customer();<br>customer.setName(&quot;Alice&quot;);<br>customer.setEmail(&quot;alice@example.com&quot;);<br>order.setCustomer(customer);<br>order.setStatus(OrderStatus.CONFIRMED);<br>order.setTotal(259.98);<br>// toBytes() / fromBytes() are generated - no Fory boilerplate<br>byte[] bytes = order.toBytes();<br>Order restored = Order.fromBytes(bytes);</pre><p><strong>Python</strong> — deserialize the same bytes:</p><pre>from ecommerce import Order<br># from_bytes() handles registration and deserialization<br>order = Order.from_bytes(bytes_from_java)<br>print(f&quot;{order.order_id}: {order.customer.name} - ${order.total}&quot;)<br># ORD-2026-001: Alice - $259.98</pre><p><strong>Go</strong> — process the order:</p><pre>import &quot;gen/ecommerce&quot;<br>var order ecommerce.Order<br>if err := order.FromBytes(bytesFromJava); err != nil {<br>    panic(err)<br>}<br>fmt.Printf(&quot;%s: %s - $%.2f\n&quot;, order.OrderId, order.Customer.Name, order.Total)</pre><p><strong>Rust</strong> — type-safe deserialization:</p><pre>use gen::ecommerce::Order;<br>let order = Order::from_bytes(&amp;bytes_from_java)?;<br>println!(&quot;{}: {} - ${:.2}&quot;, order.order_id, order.customer.name, order.total);</pre><p><strong>C++</strong> — zero-overhead access:</p><pre>#include &quot;gen/ecommerce.h&quot;<br>auto order = ecommerce::Order::from_bytes(bytes_from_java).value();<br>std::cout &lt;&lt; order.order_id() &lt;&lt; &quot;: &quot; &lt;&lt; order.customer().name()<br>          &lt;&lt; &quot; - $&quot; &lt;&lt; order.total() &lt;&lt; std::endl;</pre><p><strong>C#</strong> — strongly-typed deserialization:</p><pre>using Ecommerce;<br>var order = Order.FromBytes(bytesFromJava);<br>Console.WriteLine($&quot;{order.OrderId}: {order.Customer.Name} - ${order.Total}&quot;);</pre><p><strong>Swift</strong> — idiomatic model access:</p><pre>import Ecommerce<br>let order = try Order.fromBytes(bytesFromJava)<br>print(&quot;\(order.orderId): \(order.customer.name) - $\(order.total)&quot;)</pre><p>The same schema and generated code produce compatible bytes across supported languages with no hand-written conversion layer.</p><h3>4. Preserve Shared Identity, Not Just Values</h3><p>Because Order.customer is declared as ref Customer, shared identity is part of the schema contract:</p><pre>Customer customer = new Customer();<br>customer.setName(&quot;Alice&quot;);<br>Order first = new Order();<br>first.setOrderId(&quot;ORD-1&quot;);<br>first.setCustomer(customer);<br>Order second = new Order();<br>second.setOrderId(&quot;ORD-2&quot;);<br>second.setCustomer(customer);<br>OrderBatch batch = new OrderBatch();<br>batch.setOrders(java.util.Arrays.asList(first, second));<br>OrderBatch restored = OrderBatch.fromBytes(batch.toBytes());<br>assert restored.getOrders().get(0).getCustomer()<br>    == restored.getOrders().get(1).getCustomer();</pre><p>With a value-tree serializer, you typically rebuild this identity yourself. With Fory IDL, the ref modifier makes it part of the schema and generated code.</p><h3>The Full Feature Set</h3><h3>Nullable Fields with optional</h3><pre>message Profile {<br>    string username = 1;          // Non-optional<br>    optional string bio = 2;     // Nullable<br>    optional Address home = 3;   // Nullable struct<br>}</pre><p>LanguageNon-optionalOptionalJavaString usernameString bio (nullable)Pythonusername: strbio: Optional[str]GoUsername stringBio *stringRustusername: Stringbio: Option&lt;String&gt;C++std::stringstd::optional&lt;std::string&gt;C#string Usernamestring? BioSwiftvar username: Stringvar bio: String?</p><h3>Nested Types</h3><pre>message SearchResponse {<br>    message Result {<br>        string url = 1;<br>        string title = 2;<br>        list&lt;string&gt; snippets = 3;<br>    }<br>    list&lt;Result&gt; results = 1;<br>}</pre><p>Nested types are rendered naturally in each language: SearchResponse.Result in Java/Python/C#/Swift, SearchResponse::Result in C++, search_response::Result in Rust, SearchResponse_Result in Go.</p><h3>Imports for Multi-File Schemas</h3><pre>// common/types.fdl<br>package common;<br>message Address {<br>    string street = 1;<br>    string city = 2;<br>}<br>// models/user.fdl<br>package models;<br>import &quot;common/types.fdl&quot;;<br>message User {<br>    string name = 1;<br>    Address home = 2;  // Uses imported type<br>}</pre><pre>foryc models/user.fdl -I common/ --java_out=./gen</pre><p>The compiler resolves imports, catches import cycles, and keeps generated type registration consistent across imported schemas.</p><h3>Language-Specific Options</h3><p>Override output paths and naming conventions per language without affecting cross-language compatibility:</p><pre>package payment;<br>option java_package = &quot;com.mycorp.payment.v1&quot;;<br>option go_package = &quot;github.com/mycorp/gen/payment;paymentv1&quot;;<br>option csharp_namespace = &quot;MyCorp.Payment.V1&quot;;</pre><p>These options control <em>where</em> code is generated and how host-language names are shaped — not the underlying Fory wire format or cross-language type identity.</p><h3>Rich Type System</h3><p>Fory IDL covers the full range of types you need for production schemas:</p><p>CategoryTypesIntegersint8, int16, int32, int64, uint8–uint64, fixed_*, tagged_*Floatsfloat32, float64Stringsstring, bytesTemporaldate, timestamp, durationSpecialdecimal, any, boolCollectionslist&lt;T&gt;, map&lt;K, V&gt;Modifiersoptional, ref, ref(weak=true)</p><p>Integer types use varint encoding by default for 32/64-bit values, with explicit fixed_* and tagged_* variants when you need specific encodings.</p><h3>Migrating from Protobuf or FlatBuffers</h3><h3>Protobuf Migratio</h3><p>Already have .proto schemas? The Fory compiler can read them directly and generate Fory code from them:</p><pre>foryc existing_schema.proto --java_out=./gen --python_out=./gen</pre><p>The output uses Fory-generated types and the Fory binary protocol. Reading .proto input does <strong>not</strong> mean protobuf wire compatibility.</p><p>Key mapping:</p><ul><li>repeated T → list&lt;T&gt;</li><li>oneof → Fory union + optional field</li><li>google.protobuf.Timestamp → timestamp</li><li>google.protobuf.Any → any</li></ul><p>You can also add Fory-specific extensions in your .proto files:</p><pre>message TreeNode {<br>  TreeNode parent = 1 [(fory).weak_ref = true];<br>  repeated TreeNode children = 2 [(fory).ref = true];<br>}</pre><h3>FlatBuffers Migration</h3><p>FlatBuffers schemas work too:</p><pre>foryc existing_schema.fbs --lang java,python,go --output ./gen</pre><p>Tables become evolving messages, structs become non-evolving messages, and unions map directly to Fory unions. As with protobuf input, the generated output uses Fory types and Fory wire format rather than FlatBuffers binary compatibility. Add fory_ref:true or fory_weak_ref:true attributes where graph semantics matter.</p><h3>Inspect the Translation</h3><p>See exactly how your protobuf/FlatBuffers schema maps to Fory IDL:</p><pre>foryc schema.proto --emit-fdl</pre><p>This prints the translated .fdl to stdout — useful for reviewing the mapping before committing to the migration.</p><h3>Why Not Just Use Protobuf?</h3><p>A direct comparison with Protocol Buffers is useful because it is the default reference point for many readers.</p><p>AspectProtocol BuffersFory IDLGenerated typesTransport-model-first in many languagesIdiomatic language constructsObject graphsApplication-level IDs / rebuildsFirst-class ref / ref(weak=true)Circular referencesNot built-inBuilt into generated schemasVariant fieldsoneof / Anyunion / any in the generated modelPerformanceMature baselineOften faster on object serialization workloadsgRPC ecosystemNative, matureIn progress (active development)Schema evolutionField numbers + wire typesCompatible mode for generated schemas with field-id matchingTarget languagesMany (via plugins)Java, Python, Go, Rust, C++, C#, Swift (and growing)</p><p><strong>Use protobuf</strong> when gRPC ecosystem integration is your primary concern. <strong>Use Fory IDL</strong> when you need idiomatic domain objects, object-graph semantics, reference tracking, or maximum serialization performance.</p><p>Benchmark details and methodology live in the repository’s <a href="https://github.com/apache/fory/tree/main/docs/benchmarks">benchmark reports</a>.</p><h3>Build Integration</h3><p>The Fory compiler integrates into every major build system. Below are examples for a few common ones — the same pattern (invoke foryc as a pre-build step) applies to Cargo build scripts, Bazel rules, CMake custom commands, Swift Package Manager plugins, and others:</p><p><strong>Maven (Java):</strong></p><pre>&lt;execution&gt;<br>  &lt;id&gt;generate-fory-types&lt;/id&gt;<br>  &lt;phase&gt;generate-sources&lt;/phase&gt;<br>  &lt;goals&gt;&lt;goal&gt;exec&lt;/goal&gt;&lt;/goals&gt;<br>  &lt;configuration&gt;<br>    &lt;executable&gt;foryc&lt;/executable&gt;<br>    &lt;arguments&gt;<br>      &lt;argument&gt;${basedir}/src/main/fdl/schema.fdl&lt;/argument&gt;<br>      &lt;argument&gt;--java_out&lt;/argument&gt;<br>      &lt;argument&gt;${project.build.directory}/generated-sources/fory&lt;/argument&gt;<br>    &lt;/arguments&gt;<br>  &lt;/configuration&gt;<br>&lt;/execution&gt;</pre><p><strong>Gradle (Kotlin/Java):</strong></p><pre>task generateForyTypes(type: Exec) {<br>    commandLine &#39;foryc&#39;, &quot;${projectDir}/src/main/fdl/schema.fdl&quot;,<br>        &#39;--java_out&#39;, &quot;${buildDir}/generated/sources/fory&quot;<br>}<br>compileJava.dependsOn generateForyTypes</pre><p><strong>Go Generate:</strong></p><pre>//go:generate foryc ../schema.fdl --lang go --output .<br>package models</pre><p><strong>Python (setuptools):</strong></p><pre>class BuildWithForyIdl(build_py):<br>    def run(self):<br>        subprocess.run([&#39;foryc&#39;, &#39;schema.fdl&#39;, &#39;--python_out&#39;, &#39;src/generated&#39;], check=True)<br>        super().run()</pre><h3>Best Practices</h3><ol><li><strong>Use meaningful package names</strong>: com.myapp.models groups types logically and drives namespace generation.</li><li><strong>Use </strong><strong>optional explicitly</strong>: Don&#39;t rely on default nullability — make the intent clear in the schema.</li><li><strong>Use </strong><strong>ref only when needed</strong>: Reference tracking has a per-object cost. Use it for shared objects and cycles; skip it for value-type payloads.</li><li><strong>Use imports for shared types</strong>: Put common types (Address, Timestamp, etc.) in a shared .fdl file and import them.</li><li><strong>Use </strong><strong>--emit-fdl to review migrations</strong>: When consuming .proto or .fbs input, inspect the translated Fory IDL before committing.</li></ol><h3>Conclusion</h3><p>Apache Fory Schema IDL puts object-graph semantics into the schema model instead of leaving them to ad-hoc application code. If you need shared refs, circular structures, polymorphic fields, schema evolution, and generated models that still look idiomatic in each language, it gives you one schema and one compiler workflow for all of that.</p><p>Define your types once. Generate everywhere. Serialize object graphs without giving up idiomatic models.</p><p><strong>Get started:</strong></p><pre>pip install fory-compiler<br>foryc --help</pre><p><strong>Documentation:</strong></p><ul><li>Fory IDL Syntax: <a href="https://fory.apache.org/docs/compiler/syntax">fory.apache.org/docs/compiler/syntax</a></li><li>Compiler CLI Guide: <a href="https://fory.apache.org/docs/compiler/compiler_guide">fory.apache.org/docs/compiler/compiler_guide</a></li><li>Generated Code Reference: <a href="https://fory.apache.org/docs/compiler/generated_code">fory.apache.org/docs/compiler/generated_code</a></li><li>Cross-Language Serialization: <a href="https://fory.apache.org/docs/guide/xlang/serialization_index">fory.apache.org/docs/guide/xlang</a></li><li>Protobuf Migration: <a href="https://fory.apache.org/docs/compiler/protobuf_idl_support">fory.apache.org/docs/compiler/protobuf_idl_support</a></li><li>Benchmark Reports: <a href="https://github.com/apache/fory/tree/main/docs/benchmarks">github.com/apache/fory/tree/main/docs/benchmarks</a></li></ul><p><strong>Community:</strong></p><ul><li>GitHub: <a href="https://github.com/apache/fory">apache/fory</a></li><li>Slack: <a href="https://join.slack.com/t/fory-project/shared_invite/zt-1u8soj4qc-ieYEu7ciHOqA2mo47llS8A">Join our community</a></li><li>License: Apache License 2.0</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=00b8ffbd30d3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Apache Fory™ C++: Blazing-Fast, Type-Safe Serialization for Modern C++]]></title>
            <link>https://medium.com/@shawn.ck.yang/introducing-apache-fory-c-blazing-fast-type-safe-serialization-for-modern-c-f688f8e044ba?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/f688f8e044ba</guid>
            <category><![CDATA[cpp]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[microservices]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Thu, 12 Mar 2026 05:52:52 GMT</pubDate>
            <atom:updated>2026-03-12T05:52:52.876Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR</strong>: Apache Fory C++ is a blazing-fast, cross-language serialization framework delivering <strong>exceptional binary performance</strong> with support for <strong>polymorphic types, circular references, schema evolution, and seamless interoperability</strong> with Java, Python, Go, Rust, and JavaScript — all via modern C++17 with zero runtime reflection overhead.</p><ul><li>🐙 GitHub: <a href="https://github.com/apache/fory">https://github.com/apache/fory</a></li><li>📚 Docs: <a href="https://fory.apache.org/docs/guide/cpp">https://fory.apache.org/docs/guide/cpp</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mo1KAlj7gRJPKAPr.png" /></figure><h3>The C++ Serialization Problem</h3><p>Every C++ developer working in a polyglot environment eventually hits the same wall. Existing options force a painful choice:</p><ol><li><strong>IDL-first frameworks</strong> (Protocol Buffers, FlatBuffers): Require upfront schema compilation, lose native C++ type expressiveness, and carry significant integration friction. Every type change means regenerating code across all languages in lock-step.</li><li><strong>Reflection-based frameworks</strong> (Boost.Serialization, cereal): Limited cross-language support, no circular reference handling, no polymorphism without boilerplate. They work well within a single language but break down at system boundaries.</li><li><strong>Hand-rolled binary formats</strong>: Fast but brittle — any schema change risks silent corruption, and every new type requires manual encode/decode logic.</li></ol><p>Apache Fory C++ eliminates this trade-off. It delivers performance competitive with the fastest C++ serialization libraries while providing first-class support for polymorphism, shared/circular references, schema evolution, and <strong>binary compatibility with Java, Python, Go, Rust, and JavaScript</strong> — through a clean C++17 API.</p><h3>What Makes Apache Fory C++ Different?</h3><h3>Compile-Time Code Generation</h3><p>Most serialization frameworks pay a runtime cost for flexibility — inspecting type information through virtual dispatch or hash maps at every call. Apache Fory takes a different approach: the FORY_STRUCT macro uses C++ template metaprogramming to generate all serialization logic at compile time. The result is inlined, type-specific code with no virtual dispatch, no reflection, and no runtime overhead:</p><pre>#include &quot;fory/serialization/fory.h&quot;<br>using namespace fory::serialization;struct Person {<br>  std::string name;<br>  int32_t age;<br>  std::vector&lt;std::string&gt; hobbies;<br>  std::map&lt;std::string, std::string&gt; metadata;<br>  std::optional&lt;std::string&gt; nickname;<br>};<br>FORY_STRUCT(Person, name, age, hobbies, metadata, nickname);</pre><p>That single macro generates compile-time field metadata, efficient serialization/deserialization code via ADL (Argument-Dependent Lookup), and type registration hooks. The macro can be placed inside the class body to access private fields, or at namespace scope for third-party types.</p><h3>Cross-Language Binary Protocol</h3><p>Apache Fory C++ speaks the same binary wire format as Java, Python, Go, Rust, and JavaScript. Serialize a struct in C++, deserialize it in Python — no adaptation layer, no schema translation, no version negotiation needed. This is especially powerful for microservice architectures where different teams own different services in different languages:</p><pre>// C++: Serialize<br>auto fory = Fory::builder().xlang(true).build();<br>fory.register_struct&lt;Person&gt;(100);<br>auto bytes = fory.serialize(person).value();</pre><pre># Python: Deserialize (same binary format, same type ID)<br>fory = pyfory.Fory(xlang=True)<br>fory.register(Person, type_id=100)  # Same ID as C++<br>person = fory.deserialize(data)</pre><p>The core requirements for cross-language interoperability are consistent type IDs/Names across participating runtimes, matching canonical field names, and compatible field types for those names.</p><h3>Polymorphism via Smart Pointers</h3><p>Serializing polymorphic objects is notoriously difficult in C++. Most frameworks require manual type tagging or generate large amounts of boilerplate. Apache Fory handles it automatically: it detects polymorphic types via std::is_polymorphic&lt;T&gt; and preserves the full runtime type identity through std::shared_ptr and std::unique_ptr. When you deserialize a shared_ptr&lt;Animal&gt; that holds a Dog, you get a Dog back — no extra code required:</p><pre>struct Animal { virtual ~Animal() = default; int32_t age = 0; };<br>FORY_STRUCT(Animal, age);<br>struct Dog : Animal { std::string breed; };<br>FORY_STRUCT(Dog, FORY_BASE(Animal), breed);<br>struct Cat : Animal { std::string color; };<br>FORY_STRUCT(Cat, FORY_BASE(Animal), color);<br>struct Shelter { std::vector&lt;std::shared_ptr&lt;Animal&gt;&gt; animals; };<br>FORY_STRUCT(Shelter, animals);<br>auto fory = Fory::builder().track_ref(true).build();<br>fory.register_struct&lt;Shelter&gt;(10); fory.register_struct&lt;Dog&gt;(11); <br>fory.register_struct&lt;Cat&gt;(12);<br>Shelter s;<br>s.animals.push_back(std::make_shared&lt;Dog&gt;()); // Dog at runtime<br>s.animals.push_back(std::make_shared&lt;Cat&gt;()); // Cat at runtime<br>auto decoded = fory.deserialize&lt;Shelter&gt;(fory.serialize(s).value()).value();<br>assert(dynamic_cast&lt;Dog*&gt;(decoded.animals[0].get()) != nullptr); // Runtime type preserved!</pre><p>Fory also supports std::unique_ptr for exclusive-ownership polymorphic fields, and collections of smart pointers (std::vector&lt;std::shared_ptr&lt;Base&gt;&gt;, std::map&lt;K, std::unique_ptr&lt;Base&gt;&gt;).</p><h3>Shared/Circular Reference Tracking</h3><p>Many real-world data models contain shared objects or cycles: a parent node pointing to its children, which point back to the parent; an order referencing a customer who appears in multiple orders. Standard serialization frameworks either duplicate the data (wasting space) or crash with a stack overflow when they encounter a cycle.</p><p>With track_ref(true), Fory tracks object identity across the entire graph. Shared objects are serialized exactly once; every subsequent reference is encoded as a back-reference. Cycles terminate naturally:</p><pre>struct Node {<br>  virtual ~Node() = default;<br>  int32_t id = 0;<br>  std::vector&lt;std::shared_ptr&lt;Node&gt;&gt; neighbors;<br>};<br>FORY_STRUCT(Node, id, neighbors);<br>auto fory = Fory::builder().track_ref(true).build();<br>fory.register_struct&lt;Node&gt;(200);<br>auto node1 = std::make_shared&lt;Node&gt;(); node1-&gt;id = 1;<br>auto node2 = std::make_shared&lt;Node&gt;(); node2-&gt;id = 2;<br>node1-&gt;neighbors.push_back(node2);<br>node2-&gt;neighbors.push_back(node1);  // Cycle - handled correctly!<br>auto bytes = fory.serialize(node1).value();<br>// No stack overflow, no duplicate data - the cycle is preserved faithfully<br>auto decoded = fory.deserialize&lt;std::shared_ptr&lt;Node&gt;&gt;(bytes).value();</pre><p>This makes Fory a natural fit for graph databases, entity-component systems, and any domain model with bidirectional relationships.</p><h3>Schema Evolution</h3><p>In a microservice deployment, services update independently. A new version of the user service may add a phone field while old consumers are still running. Without schema evolution support, this forces a coordinated, big-bang deployment. Apache Fory&#39;s <strong>compatible mode</strong> removes this constraint entirely:</p><pre>// Version 1<br>struct UserV1 { std::string name; int32_t age; };<br>FORY_STRUCT(UserV1, name, age);<br>// Version 2 - new fields added independently<br>struct UserV2 { std::string name; int32_t age; std::string email; };<br>FORY_STRUCT(UserV2, name, age, email);<br>auto fory_v1 = Fory::builder().compatible(true).xlang(true).build();<br>auto fory_v2 = Fory::builder().compatible(true).xlang(true).build();<br>fory_v1.register_struct&lt;UserV1&gt;(100);<br>fory_v2.register_struct&lt;UserV2&gt;(100);  // Same type ID enables evolution<br>auto bytes = fory_v1.serialize(UserV1{&quot;Alice&quot;, 30}).value();<br>auto v2 = fory_v2.deserialize&lt;UserV2&gt;(bytes).value();<br>assert(v2.name == &quot;Alice&quot; &amp;&amp; v2.email == &quot;&quot;);  // Default for missing field</pre><p>In compatible mode, fields are matched by name rather than position. New fields receive C++ default values when missing; removed fields are safely skipped. This enables rolling upgrades and independent service deployments without any serialization errors.</p><h3>Row Format: Zero-Copy Analytics</h3><p>Beyond object graph serialization, Apache Fory C++ implements a <strong>row-based binary format</strong> designed for analytics workloads. The row format stores data in a contiguous memory layout with a null bitmap, fixed-size slots for primitives, and a variable-length section for strings and nested objects. This enables <strong>O(1) random field access by index</strong> — you can read a single field from a large struct without touching the rest of the data.</p><p>This is particularly valuable in data pipelines and OLAP workloads where only a small subset of fields are queried per record:</p><pre>#include &quot;fory/encoder/row_encoder.h&quot;<br>using namespace fory::row::encoder;<br>struct SensorReading {<br>  int32_t sensor_id; double temperature; std::string location;<br>  FORY_STRUCT(SensorReading, sensor_id, temperature, location);<br>};<br>RowEncoder&lt;SensorReading&gt; encoder;<br>encoder.encode({42, 23.5, &quot;rack-B&quot;});<br>auto row = encoder.get_writer().to_row();<br>// Read any field in O(1) - no deserialization of unused fields<br>int32_t id    = row-&gt;get_int32(0);<br>double  temp  = row-&gt;get_double(1);<br>auto    loc   = row-&gt;get_string(2);</pre><p>For zero-copy access into an existing buffer (e.g., from a memory-mapped file or network receive buffer), Fory can point a Row directly at the memory without copying:</p><pre>auto src = encoder.get_writer().to_row();<br>fory::row::Row view(src-&gt;schema());<br>view.point_to(src-&gt;buffer(), src-&gt;base_offset(), src-&gt;size_bytes());  // Zero-copy view<br>int32_t id = view.get_int32(0);  // Reads directly from the original buffer</pre><p>Use the row format for analytics, OLAP-style workloads, and partial field access. Use object graph serialization for full object round-trips with references and polymorphism.</p><h3>Installation</h3><p>Fory C++ requires a C++17-compatible compiler (GCC 7+, Clang 5+, MSVC 2017+) and supports both CMake and Bazel build systems.</p><h3>CMake (FetchContent)</h3><p>The simplest integration is via CMake’s FetchContent module, which fetches and builds Fory as part of your project:</p><pre>cmake_minimum_required(VERSION 3.16)<br>project(my_project LANGUAGES CXX)<br>set(CMAKE_CXX_STANDARD 17)<br>include(FetchContent)<br>FetchContent_Declare(fory<br>    GIT_REPOSITORY https://github.com/apache/fory.git<br>    GIT_TAG v0.15.0<br>    SOURCE_SUBDIR cpp)<br>FetchContent_MakeAvailable(fory)<br>add_executable(my_app main.cc)<br>target_link_libraries(my_app PRIVATE fory::serialization)</pre><h3>Bazel</h3><p>For Bazel-based projects, add Fory as a module dependency:</p><pre>bazel_dep(name = &quot;fory&quot;, version = &quot;0.15.0&quot;)<br>git_override(module_name = &quot;fory&quot;,<br>    remote = &quot;https://github.com/apache/fory.git&quot;,<br>    commit = &quot;v0.15.0&quot;)</pre><pre>cc_binary(<br>    name = &quot;my_app&quot;, <br>    srcs = [&quot;main.cc&quot;],<br>    deps = [&quot;@fory//cpp/fory/serialization:fory_serialization&quot;]<br>)</pre><h3>Native Serialization</h3><p>For pure C++ applications without cross-language requirements, disabling xlang produces a more compact binary encoding because no cross-language type metadata is emitted. This is the fastest possible path:</p><pre>auto fory = Fory::builder()<br>    .xlang(false)      // Native C++ mode — tighter encoding<br>    .track_ref(false)  // Disable if no shared/circular refs<br>    .build();<br><br>fory.register_struct&lt;Address&gt;(1);<br>fory.register_struct&lt;Person&gt;(2);<br>// Serialize<br>auto result = fory.serialize(person);<br>if (!result.ok()) { std::cerr &lt;&lt; result.error().to_string(); return 1; }<br>std::vector&lt;uint8_t&gt; bytes = std::move(result).value();<br>// Deserialize<br>auto decoded = fory.deserialize&lt;Person&gt;(bytes);<br>assert(decoded.ok() &amp;&amp; person == decoded.value());</pre><p>FORY_STRUCT handles several important C++ patterns that commonly arise in production codebases:</p><pre>// Private fields — place macro in public: section<br>class Secure {<br>  int32_t secret_; std::string token_;<br>public:<br>  FORY_STRUCT(Secure, secret_, token_);<br>};<br>// Inheritance - FORY_BASE includes base class fields<br>struct Derived : Base {<br>  std::string extra;<br>  FORY_STRUCT(Derived, FORY_BASE(Base), extra);<br>};<br>// External/third-party types - use at namespace scope (public fields only)<br>namespace ext { struct Coord { double lat, lon; }; }<br>FORY_STRUCT(ext::Coord, lat, lon);</pre><h3>Error Handling</h3><p>All Fory operations return Result&lt;T, Error&gt;, making error handling explicit and composable. The FORY_TRY macro provides a concise early-return pattern for functions that propagate errors:</p><pre>// Option 1: Conditional check<br>auto r = fory.serialize(obj);<br>if (r.ok()) { auto bytes = std::move(r).value(); }<br>else { std::cerr &lt;&lt; r.error().to_string(); }<br>// Option 2: FORY_TRY macro for early return<br>FORY_TRY(bytes, fory.serialize(obj));<br>// Use bytes directly - any error propagates automatically</pre><h3>Thread Safety</h3><p>Fory provides two variants with different threading guarantees. Choose based on whether your serialization is centralized (shared instance) or distributed across threads:</p><pre>// Single-threaded (fastest) — one instance per thread, no synchronization overhead<br>auto fory = Fory::builder().build();<br>// Thread-safe - shared across threads via an internal instance pool<br>auto fory = Fory::builder().build_thread_safe();<br>fory.register_struct&lt;MyType&gt;(1);  // Register all types before sharing<br>std::thread t([&amp;]() { fory.serialize(obj); });  // Safe to call concurrently</pre><h3>Cross-Language Serialization</h3><h3>Without IDL</h3><p>When you control both sides of the wire and can coordinate type definitions manually, the simplest approach is to register types with matching numeric IDs in each language. This requires no additional tooling and works well for small, stable schemas:</p><pre>// C++<br>auto fory = Fory::builder().xlang(true).build();<br>fory.register_struct&lt;Order&gt;(201);<br>auto bytes = fory.serialize(order).value();</pre><pre>// Java — same binary format, same type ID<br>Fory fory = Fory.builder().withLanguage(Language.XLANG).build();<br>fory.register(Order.class, 201);<br>Order order = (Order) fory.deserialize(bytes);</pre><pre># Python — same binary format, same type ID<br>fory = pyfory.Fory(xlang=True)<br>fory.register(Order, type_id=201)<br>order = fory.deserialize(data)</pre><p><strong>Field matching</strong>: In cross-language mode, field names are normalized to snake_case and matched by that canonical name. Ordering follows Fory’s xlang field-order rules (not simple alphabetical ordering), so keep names semantically consistent across languages.</p><h3>With the Fory Schema IDL Compiler</h3><p>As schemas grow and span more services and teams, manually maintaining consistent field names, type IDs, and type definitions across five languages becomes error-prone. The <strong>Fory Schema IDL Compiler</strong> (foryc) solves this by letting you define types once in a .fdl file and generating idiomatic, production-ready code for every target language. The generated code includes typed accessors, serialization macros, registration helpers, and to_bytes()/from_bytes() helpers — so you never write serialization plumbing by hand.</p><h4>1. Install the compile</h4><pre>pip install fory-compiler<br>foryc --help</pre><h4>2. Write a schema (ecommerce.fdl)</h4><p>Fory IDL syntax is concise and deliberately close to protobuf, so it is easy to pick up. Field modifiers like optional, ref, and list map directly to idiomatic C++ types:</p><pre>package ecommerce;<br><br>enum OrderStatus {<br>    PENDING = 0; CONFIRMED = 1; SHIPPED = 2; DELIVERED = 3;<br>}<br>message Address {<br>    string street = 1; string city = 2; string country = 3;<br>}<br>message Customer {<br>    string           id      = 1;<br>    string           name    = 2;<br>    optional string  email   = 3;   // Nullable: maps to std::optional&lt;std::string&gt;<br>    optional Address address = 4;<br>}<br>message OrderItem {<br>    string  sku        = 1;<br>    int32   quantity   = 2;<br>    float64 unit_price = 3;<br>}<br>// Discount can be either a fixed amount or a percentage - modelled as a union<br>message FixedDiscount   { float64 amount     = 1; }<br>message PercentDiscount { float64 percentage = 1; }<br>// union maps to std::variant&lt;FixedDiscount, PercentDiscount&gt; in C++<br>union Discount {<br>    FixedDiscount   fixed   = 1;<br>    PercentDiscount percent = 2;<br>}<br>message Order {<br>    string            order_id   = 1;<br>    ref Customer      customer   = 2;  // ref: std::shared_ptr + reference tracking<br>    list&lt;OrderItem&gt;   items      = 3;  // list: std::vector&lt;OrderItem&gt;<br>    OrderStatus       status     = 4;<br>    float64           total      = 5;<br>    optional string   notes      = 6;<br>    timestamp         created_at = 7;<br>    optional Discount discount   = 8;  // optional union field<br>}</pre><p>The IDL type system maps cleanly to native C++ constructs. union is a first-class IDL construct that generates a std::variant-based wrapper class in C++, with typed case accessors (is_fixed(), as_fixed(), etc.) and a visit() method. Here is the full set of field modifiers and their C++ equivalents:</p><p>ModifierC++ typePurposeoptional Tstd::optional&lt;T&gt;Nullable fieldref Tstd::shared_ptr&lt;T&gt;Shared / circular referenceref(weak=true) Tfory::serialization::SharedWeak&lt;T&gt;Weak reference (breaks cycles)list&lt;T&gt;std::vector&lt;T&gt;Ordered listmap&lt;K,V&gt;std::map&lt;K,V&gt;Key-value map</p><h4>3. Generate code</h4><p>foryc generates a single header file per schema for C++, and equivalent files for every other target language. All generated files use the same type IDs derived from the package and type names, guaranteeing binary compatibility without any manual coordination:</p><pre># Generate C++ header directly under ./generated<br>foryc ecommerce.fdl --cpp_out ./generated<br># Generate multiple languages with explicit output directories<br>foryc ecommerce.fdl --cpp_out ./generated --java_out ./java/src/main/java --python_out ./python/gen --go_out ./go/gen --rust_out ./rust/gen</pre><p>The output structure for C++ is one header per schema file under the directory passed to --cpp_out. For example, --cpp_out ./generated produces generated/ecommerce.h. The header contains all types under the ecommerce:: namespace, with FORY_STRUCT macros and a register_types() helper already wired up.</p><h4>4. Use the generated C++ code</h4><p>The generated header provides final classes with typed accessors and to_bytes()/from_bytes() helpers. There is no manual Fory instance setup required — the helpers manage it internally:</p><pre>#include &quot;generated/ecommerce.h&quot;<br>ecommerce::Order order;<br>order.set_order_id(&quot;ORD-2025-001&quot;);<br>order.mutable_customer()-&gt;set_name(&quot;Alice&quot;);<br>order.set_status(ecommerce::OrderStatus::CONFIRMED);<br>order.set_total(159.98);<br>// to_bytes()/from_bytes() are generated - no Fory boilerplate needed<br>auto bytes = order.to_bytes().value();<br>auto restored = ecommerce::Order::from_bytes(bytes).value();<br>assert(restored.order_id() == &quot;ORD-2025-001&quot;);</pre><p>Because the generated Java, Python, and Go code uses the same type IDs, bytes serialized by the C++ to_bytes() helper can be deserialized by the Java fromBytes() or Python from_bytes() helpers out of the box — no extra configuration required.</p><h3>Supported Types</h3><p>Apache Fory C++ supports a comprehensive set of types covering all common C++ data structures and cross-language primitives:</p><p>CategoryC++ TypesPrimitivesbool, int8_t…int64_t, uint8_t…uint64_t, float, doubleStringsstd::string, std::string_view, std::u16stringCollectionsstd::vector&lt;T&gt;, std::set&lt;T&gt;, std::unordered_set&lt;T&gt;, std::map&lt;K,V&gt;, std::unordered_map&lt;K,V&gt;Optional/Unionstd::optional&lt;T&gt;, std::variant&lt;Ts...&gt;Smart Pointersstd::shared_ptr&lt;T&gt; (ref tracking + polymorphism), std::unique_ptr&lt;T&gt;, fory::serialization::SharedWeak&lt;T&gt;Temporalstd::chrono::nanoseconds, fory::serialization::Timestamp, fory::serialization::DateEnumsScoped/unscoped enums; use FORY_ENUM for non-continuous valuesUser structsAny type annotated with FORY_STRUCT</p><p>All collection element and map value types can be arbitrarily nested, including structs, smart pointers, and std::optional.</p><h3>Configuration Reference</h3><p>Fory instances are constructed through a fluent builder API. All options have sensible defaults, so most applications only need to set one or two:</p><pre>auto fory = Fory::builder()<br>    .xlang(true)                // Cross-language binary protocol (default: true)<br>    .compatible(true)           // Schema evolution / compatible mode (default: false)<br>    .track_ref(true)            // Shared/circular reference tracking (default: true)<br>    .max_dyn_depth(10)          // Max polymorphic nesting depth (default: 5)<br>    .check_struct_version(true) // Validate struct hash on deserialization (default: false)<br>    .build();                   // Single-threaded; use build_thread_safe() for multi-thread</pre><p><strong>Tuning guide</strong>: Disable compatible for maximum throughput when schema changes are coordinated (same binary deployed together). Disable track_ref for pure value types with no sharing or cycles — it eliminates per-object reference bookkeeping. Use xlang(false) for C++-only deployments to get a more compact binary encoding.</p><h3>Benchmarks</h3><p>Apache Fory delivers exceptional performance across diverse data shapes. The combination of compile-time code generation, variable-length integer encoding, and a carefully designed binary protocol yields major gains versus text formats and strong results versus Protocol Buffers. In the current C++ benchmark report, Fory throughput vs Protobuf ranges from about <strong>1.1x to 12.2x</strong> depending on workload and operation:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2gAvId7Yt4juVFOz.png" /></figure><p>The C++ implementation achieves similar relative speedups to the Java implementation. Because both share the same binary protocol design, and C++ serialization code is generated at compile time (eliminating the JIT warm-up cost), C++ performance is competitive or superior for latency-sensitive workloads.</p><p>Serialized Data Sizes (bytes)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5aQpUGDFQ1KdsmSRZThNfA.png" /></figure><h3>Conclusion</h3><p>Apache Fory C++ brings together a set of capabilities that no other C++ serialization library delivers as a cohesive package:</p><ul><li><strong>Performance</strong>: Template-based compile-time codegen eliminates all runtime reflection overhead; a highly efficient binary protocol minimizes both serialized size and CPU cycles</li><li><strong>Cross-language</strong>: The same binary format works natively with Java, Python, Go, Rust, and JavaScript</li><li><strong>Native C++ idioms</strong>: std::shared_ptr, std::optional, std::variant, fory::serialization::SharedWeak — all handled naturally</li><li><strong>Production-ready features</strong>: Polymorphism, circular references, schema evolution, thread safety out of the box</li><li><strong>Schema-first option</strong>: The Fory IDL Compiler generates consistent, idiomatic code across all languages from a single .fdl definition — no more manually synchronizing type IDs across codebases</li></ul><p>Whether you are building a high-performance game server, a polyglot microservice backend, a real-time analytics pipeline, or an embedded system serializing complex domain models, Apache Fory C++ has you covered.</p><p><strong>Get started:</strong></p><pre>git clone https://github.com/apache/fory.git<br>cd fory/examples/cpp/hello_world<br>cmake -B build -DCMAKE_BUILD_TYPE=Release &amp;&amp; cmake --build build<br>./build/hello_world</pre><p><strong>Documentation:</strong></p><ul><li>C++ Serialization Guide: <a href="https://fory.apache.org/docs/guide/cpp">fory.apache.org/docs/guide/cpp</a></li><li>Fory Schema IDL Compiler: <a href="https://fory.apache.org/docs/compiler">fory.apache.org/docs/compiler</a></li><li>Xlang Serialization Spec: <a href="https://fory.apache.org/docs/specification/xlang_serialization_spec/">fory.apache.org/docs/specification</a></li></ul><p><strong>Community:</strong></p><ul><li>GitHub: <a href="https://github.com/apache/fory">apache/fory</a></li><li>Slack: <a href="https://join.slack.com/t/fory-project/shared_invite/zt-1u8soj4qc-ieYEu7ciHOqA2mo47llS8A">Join our community</a></li><li>License: Apache License 2.0</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f688f8e044ba" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Awex: An Ultra‑Fast Weight Sync Framework Powering Trillion‑Scale Reinforcement Learning]]></title>
            <link>https://medium.com/@shawn.ck.yang/awex-an-ultra-fast-weight-sync-framework-powering-trillion-scale-reinforcement-learning-766ebc79f58b?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/766ebc79f58b</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[reinforcement-learning]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[large-language-models]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Thu, 20 Nov 2025 08:46:10 GMT</pubDate>
            <atom:updated>2025-11-20T09:07:59.488Z</atom:updated>
            <content:encoded><![CDATA[<h3>Awex: An Ultra‑Fast Weight Sync Framework for Second‑Level Updates in Trillion‑Scale Reinforcement Learning</h3><p>Over the past few years,<strong> Reinforcement Learning (RL)</strong> has become a core technology for<strong> post-training</strong> large language models. From ChatGPT’s RLHF to DeepSeek/Claude/Llama’s post-training systems, all rely on reinforcement learning to align models with <strong>human preferences</strong> and enhance their <strong>reasoning capabilities</strong>, further expanding the boundaries of model intelligence.</p><p>In October this year, Ant Group open-sourced two industry-leading trillion-parameter models: the non-reasoning Ling-1T and the reasoning model Ring-1T. <strong>Ring-1T</strong> is built on our high-performance weight exchange framework <strong>Awex (Asystem Weight Exchange Framework)</strong>, achieving <strong>trillion-parameter-level weight synchronization within 5–10 seconds across thousands of GPU clusters</strong>.</p><p><a href="https://github.com/inclusionAI/asystem-awex">Awex</a> is now officially open source: <a href="https://github.com/inclusionAI/asystem-awex">https://github.com/inclusionAI/asystem-awex</a></p><p>This article provides an in-depth introduction to Awex’s design philosophy, core challenges, solutions, and performance benchmarks.</p><h3>Problems and Challenges</h3><p>In large model reinforcement learning training, to improve inference efficiency, the <strong>Rollout</strong> phase typically uses independent high-performance <strong>inference engines</strong> (such as SGLang/vLLM). Weight synchronization refers to the process of <strong>transferring model weights</strong> <strong>from the training engine to the inference engin</strong>e after each training step, ensuring that inference uses the latest parameters to generate samples, forming a complete training loop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7A49K79ST0_v_eC7.png" /></figure><p>As RL model parameters and training cluster scales expand, along with the evolution and changes in different RL algorithms, weight synchronization faces the following technical challenges:</p><ul><li><strong>Heterogeneous parallelism strategy adaptation between training and inference engines</strong>: Training engines typically adopt DP + PP/VPP + TP + EP + CP (*), while inference engines mostly use DP + TP + EP. Different parallelism strategies lead to inconsistent weight sharding, requiring efficient Resharding mechanisms;</li><li><strong>Differential weight precision and formats between training and inference engines</strong>: Inference engines often use low precision (FP8/INT4) to improve performance, while training engines use high precision (BF16/FP32) to ensure convergence. Different engines have different requirements for weight layout and fusion;</li><li><strong>Exchange efficiency challenges from growing weight parameters</strong>: With the continuous evolution of Scaling Law, large model parameter scales have gradually grown to trillion-level. Transmitting 100TB+ data across thousand-GPU clusters makes transmission time a training bottleneck;</li><li><strong>Co-located and separated deployment modes</strong>: Synchronous RL algorithms mostly adopt co-located mode, where training and inference share GPUs time-divisionally to maximize resource utilization; asynchronous RL algorithms use separated mode, where training and inference use different GPUs and run in parallel;</li><li><strong>Dynamic scaling of inference instances</strong>: During training iterations, model outputs gradually become longer and Rollout time increases, requiring dynamic scaling of inference instances. Weight synchronization needs to support new instance integration.</li></ul><p>(*Note: Common heterogeneous parallelism strategies include: Data Parallelism (DP), Pipeline Parallelism (PP), Tensor Parallelism (TP), Expert Parallelism (EP), and Context Parallelism (CP))</p><h3>Limitations of Existing Systems</h3><p>Existing weight transfer solutions mainly fall into two categories, both still facing <strong>performance bottlenecks</strong> in scenarios with large model parameters:</p><ul><li><strong>Weight exchange via distributed file systems</strong>: After completing a single training step, the training engine gathers model weights layer by layer and writes them to a shared file system, after which the inference engine loads the model weights from the shared file system. Limited by the performance of shared file systems, a <strong>10B parameter</strong> model requires <strong>several minutes</strong>, while a <strong>trillion-parameter</strong> model takes <strong>hours or more</strong>;</li><li><strong>Layer-by-layer weight synchronization via NCCL + Full Tensor</strong>: This is the weight exchange method adopted by some open-source frameworks. The training engine <strong>gathers the full tensor layer by layer</strong> on each GPU card, then maps it to the inference engine via CUDA IPC for weight loading. This approach executes serially layer by layer, cannot fully utilize bandwidth, has significant redundant transmission when TP is large, and still requires <strong>minutes or more of latency</strong> for large model parameters.</li></ul><p>Considering these limitations, I began exploring whether a <strong>zero‑redundancy, transport‑based weight‑exchange framework</strong> could be built — one that avoids full‑tensor gathering and redundant bandwidth consumption.</p><p>The idea was simple: instead of collecting complete weights on each training worker, the training side would <strong>send only the tensor shards needed by each inference worker</strong>. If these shard‑level transfers occurred <strong>concurrently</strong> — without global synchronization or layer‑wise serialization — redundant communication would be eliminated, bandwidth usage maximized, and weight‑update latency greatly reduced even for very large models.</p><p>Those ideas came together and finally became <a href="https://github.com/inclusionAI/asystem-awex"><strong>Awex</strong></a>: a zero‑redundancy P2P weight‑exchange framework.</p><h3>Awex Introduction</h3><p>Awex is <strong>a weight synchronization framework between training and inference engines designed for ultimate performance</strong>, solving the core challenge of synchronizing training weight parameters to inference models in the RL workflow. It can <strong>complete TB-scale large-scale parameter </strong>synchronization<strong> within seconds</strong>, significantly reducing RL model training latency. Main features include:</p><ul><li>⚡ <strong>Blazing synchronization performance</strong>: Full synchronization of trillion-parameter models across thousand-GPU clusters within 6 seconds, industry-leading performance;</li><li>🔄 <strong>Unified model adaptation layer</strong>: Automatically handles differences in parallelism strategies between training and inference engines and tensor format/layout differences, compatible with multiple model architectures;</li><li>💾 <strong>Zero-redundancy Resharding transmission and in-place updates</strong>: Only transfers necessary shards, updates inference-side memory in place, avoiding reallocation and copy overhead;</li><li>🚀 <strong>Multi-mode transmission support</strong>: Supports multiple transmission modes including NCCL, RDMA, and shared memory, fully leveraging NVLink/NVSwitch/RDMA bandwidth and reducing long-tail latency;</li><li>🔌 <strong>Heterogeneous deployment compatibility</strong>: Adapts to co-located/separated modes, supports both synchronous and asynchronous RL algorithm training scenarios, with RDMA transmission mode supporting dynamic scaling of inference instances;</li><li>🧩 <strong>Flexible pluggable architecture</strong>: Supports customized weight sharing and layout behavior for different models, while supporting integration of new training and inference engines.</li></ul><p>GitHub Repo: <a href="https://github.com/inclusionAI/asystem-awex">https://github.com/inclusionAI/asystem-awex</a></p><h3>Awex Overall Design</h3><p>The Awex weight exchange framework consists primarily of three components:</p><ul><li><strong>WeightWriter</strong>: Runs within each training process, responsible for metadata collection and reporting of weight shards for the current training process, weight convert, resharding transfer plan construction, weight transmission, and other functions;</li><li><strong>WeightReader</strong>: Runs on the control process of each inference instance, which starts a WorkerWeightsReader on each GPU managed by the inference instance, corresponding to the WeightWriter of the training process. Responsible for metadata collection and reporting of weight shards for each inference process, weight convert, resharding transfer plan construction, weight reception, and other functions;</li><li><strong>MetaServer</strong>: Job-level global server for service discovery and weight metadata exchange between training and inference engines, as well as event notification functions in co-located scenarios;</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Zc4clS0XWpObfKIO.png" /></figure><p>The core functional modules of weight exchange consist mainly of 5 parts, which I will introduce one by one:</p><ul><li><strong>Unified training-inference weight convert</strong>: Responsible for converting weights from training and inference engines with <strong>different parallelism strategies and tensor layouts</strong> into a <strong>unified format</strong> for subsequent weight metadata calculation and weight transmission;</li><li><strong>Global weight metadata calculation and exchange</strong>: After converting training and inference weights into a unified format, collects all weight shard metadata from each worker and reports to Meta Server for subsequent weight transmission plan construction;</li><li><strong>P2P weight transmission execution plan</strong>: Training and inference engines obtain global weight shard metadata from all workers, then separately construct peer-to-peer deterministic transfer plan for sending and receiving;</li><li><strong>NCCL weight transmission</strong>: Uses NCCL’s send/recv API for peer-to-peer weight transmission based on the constructed transmission plan;</li><li><strong>RDMA weight transmission</strong>: Uses NUMA affinity and RDMA communication for globally load-balanced transfer plan for weight updates;</li></ul><p>Awex also supports tensor-level validation of weights, comparing weights loaded through file system mode with those loaded through transmission mode at the tensor level for fine-grained comparison, ensuring the correctness of the transmission mode. Due to space limitations, this will not be expanded here.</p><h3>(1) Unified Training-Inference Weight Convert</h3><p>Due to different computational workloads, training and inference engines generally adopt different parallelism strategies. Megatron training engine uses 5D parallelism strategy, DeepSpeed/FSDP uses Zero + DP data parallelism, while SGLang and VLLM inference engines mostly use DP + TP + EP. Additionally, different engines perform <strong>fusion, transposition, and quantization</strong> optimizations on weights after loading to adapt to high-performance operators.</p><p>To eliminate differences between different engines for subsequent weight exchange, Awex constructs a <strong>unified weight convert layer</strong> that performs the following converts:</p><ul><li><strong>Weight splitting</strong>: Splits merged weights (such as FFN’s gate/up) into independent weights, supporting cross-TP Resharding;</li><li><strong>Weight name unification</strong>: Converts all internal weights from all engines to the same namespace, establishing weight mapping relationships between training and inference engines;</li><li><strong>Attention weight ReGroup</strong>: On the training engine side, regroups and aligns QKV weights along the inference engine’s TP/DPAttention parallelism strategy, avoiding shard explosion from fine-grained splitting;</li><li><strong>Quantization, precision, and format conversion</strong>: Automatically converts weights on the training side <strong>according to the precision and format of the inference side</strong>, and this low-precision conversion can also reduce the amount of transmitted data.</li></ul><p>The entire weight convert adaptation layer is implemented as a <strong>pluggable structure</strong> that can be fully customized at the engine layer, model weight convert, and sharding layer to meet the customization needs of complex scenarios.</p><h3>(2) Global Weight Metadata Management</h3><p>Each training and inference process needs to <strong>be aware of the weight metadata of all training and inference processes globally</strong> for constructing subsequent weight transfer plan. Awex also performs <strong>consistency validation of weight metadata between training and inference</strong> at this step. The main workflow is as follows:</p><ul><li>Each process in the training engine performs weight convert and obtains metadata for the converted shards</li><li>Through all_gather_object, each rank obtains global training shard metadata</li><li>Rank0 on the training side serializes global metadata and reports it to Meta Server</li><li>Inference instance 0 on the inference side performs similar work; other inference instances have identical metadata and don’t need additional computation</li><li>All training and inference processes obtain global metadata from MetaServer</li><li>Training and inference engines each perform shard-level metadata consistency and compatibility validation</li></ul><h3>(3) P2P Weight Transmission Execution Plan</h3><p>After obtaining global weight metadata, Awex constructs a <strong>deterministic point-to-point transmission plan</strong> within each training and inference process.</p><p><strong>Core Strategy</strong> (NCCL mode):</p><ul><li>For each replica of the same tensor shard, assign training shards to inference shards through Round Robin to ensure uniform pulling;</li><li>For overlapping shard intervals, if perfectly aligned, directly map; otherwise, use two sends to different shards;</li><li>Pre-filter shards related to the current process to avoid constructing a global plan (shards can reach tens of millions for trillion-parameter models);</li><li>Ensure strict order consistency of NCCL send/recv;</li></ul><p>RDMA is more flexible and uses a separate transmission plan, which won’t be covered in this article.</p><h3>(4) NCCL Weight Transmission</h3><p>Awex supports two transmission modes: NCCL (NVIDIA Collective Communications Library) and RDMA (Remote Direct Memory Access). NCCL mode is more user-friendly, while RDMA mode is more flexible with higher performance.</p><p>NCCL transmission mode primarily uses NCCL’s send/recv interface for weight transmission. There are some implementation differences in Awex for separated and co-located modes, which I will detail here.</p><p><strong>NCCL Separated Weight Transmission</strong></p><p>In separated transmission mode, Awex first constructs a joint training-inference NCCL Process Group for subsequent weight transmission from training to inference. Next, based on the NCCL send and transfer plan created during initialization, <strong>P2P peer-to-peer ordered weight sending and receiving</strong> is performed on each process of the training and inference engines. The overall workflow is as follows:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6_ri40Hb_DD0vP5e.png" /></figure><p><strong>CUDA IPC Co-located Zero-Copy Weight Mapping</strong></p><p>Since the rank count of a single NCCL communication group can only equal the number of GPU cards, and in the training-inference co-located case, the rank count is twice the number of GPU cards, a joint training-inference communication group cannot be directly established.</p><p>In this case, Awex uses <strong>CUDA IPC to zero-copy map the training process’s GPU memory to the inference process</strong>, establishes a global communication group for all inference processes, then uses this communication group for NCCL send/recv to complete weight exchange from training to inference engines:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T9oN-cFRdwMa6Nxu.png" /></figure><p>In implementation, I also made some <strong>performance optimizations</strong>:</p><ul><li><strong>Problem</strong>: Each CUDA IPC Handle’s Open/Close has significant overhead; MOE and other models may have thousands to tens of thousands of weight tensors per card requiring IPC serialization;</li><li><strong>Solution</strong>: Before IPC serialization, merge tensors by shape and dtype, reducing the count to dozens, greatly reducing CUDA IPC overhead;</li></ul><p>(<strong>Note</strong>: CUDA IPC does not support CUDA virtual memory. Future plans include allocating additional physical memory space for weight merging and transmission when enabling virtual GPU memory in the training engine)</p><h3>(5) RDMA Weight Transmission</h3><p>Although NCCL transmission mode can already significantly improve weight exchange performance, NCCL mode has two main limitations:</p><ol><li><strong>NCCL versions on training and inference sides need to remain compatible</strong>, otherwise NCCL transmission may hang, preventing independent updates and iterations of training and inference engines;</li><li><strong>NCCL’s static topology is not friendly to communication domain scaling</strong>, as continued RL training causes inference outputs to gradually grow and workload to increase, requiring scaling of inference instances. NCCL needs to destroy the entire communication group and rebuild;</li></ol><p>Considering these two reasons, an RDMA-based transmission implementation has also been added to Awex.</p><p>The weights exchange process is similiar to NCCL. The main difference is that RDMA mode will copy gpu tensors to cpu-pinned memory, which is registered for RDMA access:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FBv3x83JIw25KV_T-WswGA.png" /></figure><p><strong>RDMA Mode Advantages</strong>:</p><ul><li>Removes NCCL version binding, supports independent iteration of training and inference engines</li><li>More flexible transmission plan optimization space</li><li>Supports dynamic scaling of inference instances</li><li>Further performance improvement (1T model from 20 seconds to 6 seconds)</li></ul><p>RDMA mode implementation will be open-sourced soon. Stay tuned.</p><h3>Performance Benchmarks</h3><p>On thousand-GPU scale clusters, Awex using NCCL transmission can exchange<strong> 10B-scale model </strong>weights<strong> </strong>within<strong> one second</strong>, and <strong>1T-scale model weights </strong>within<strong> twenty seconds</strong>. Using RDMA for transmission, <strong>1T model weight exchange </strong>time can be further <strong>reduced to 6 seconds</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jdTemNbC8koDfwZrakfcFg.png" /></figure><h3>Quick Start Get Started</h3><p>Awex is a pure Python library that can be installed and used with one command, supporting Python 3.8 and above.</p><pre>pip install awex</pre><p>Megatron training engine weight sending example:</p><pre>from awex import NCCLWeightsWriter<br>from awex.engine.mcore import MegatronEngine<br># init<br>train_engine = MegatronEngine(awex_config, hf_config, mcore_model)<br>writer = NCCLWeightsWriter(train_engine)<br>writer.initialize()<br># write weights<br>writer.write_weights(step_id=1)</pre><p>SGLang inference engine weight update example:</p><pre>from awex import WeightsReader<br>from awex.engine.sglang import SGLangEngine<br>import sglang as sgl<br><br>sgl_engine = sgl.Engine(model_path=&quot;xxx&quot;, tp_size=2, random_seed=42)<br>inference_engine = SGLangEngine(awex_confg, sgl_engine)<br>reader = WeightsReader(inference_engine)<br>reader.initialize()<br># update weights<br>reader.update_weights(step_id=1)</pre><h3>Future Roadmap</h3><p>Awex is one of the core components of our reinforcement learning system, which serves as the solid foundation for training Bailing trillion-parameter models. Ant Group will gradually open-source other core RL components of ASystem in the future to further improve the open-source reinforcement learning training ecosystem. Stay tuned!</p><p>The current open-source version of Awex supports <strong>Megatron</strong> and <strong>SGLang</strong> engines, with much work remaining to be done. We look forward to collaborating with the community to gradually expand support for more mainstream engines with the power of the community:</p><ul><li>🔧 <strong>Training engines we hope to support</strong>: DeepSpeed, FSDP, etc.</li><li>🚀 <strong>Inference engines we hope to support</strong>: vLLM, TensorRT-LLM, etc.</li><li>🤖 <strong>Model adaptation</strong>: Built-in out-of-the-box support for more mainstream models</li></ul><p>We welcome every developer interested in reinforcement learning and large language models to use Awex, provide valuable feedback and suggestions, and work together to drive continuous innovation in reinforcement learning systems!</p><ul><li>📦 <strong>GitHub Repository</strong>: <a href="https://github.com/inclusionAI/awex">https://github.com/inclusionAI/awex</a></li><li>⭐ Welcome to Star and Fork, and we look forward to your PRs!</li></ul><p>We also welcome you to follow the latest releases of Ant’s Bailing models:</p><ul><li>🤗 Hugging Face: <a href="https://huggingface.co/inclusionAI">https://huggingface.co/inclusionAI</a></li><li>🤖 ModelScope Community: <a href="https://www.modelscope.cn/models/inclusionAI">https://www.modelscope.cn/models/inclusionAI</a></li></ul><h3>About Me</h3><p><a href="https://github.com/chaokunyang">Shawn Yang</a>, author of the <a href="https://github.com/inclusionAI/asystem-awex">Awex</a> framework and creator &amp; PMC Chair of the <a href="https://github.com/apache/fory">Apache Fory serialization framework</a>, Active open‑source contributor.</p><p>Experienced in distributed systems and high‑performance computing across streaming and batch engines, online machine learning systems, the Ray ecosystem, scientific computing, multimedia and multimodal processing, training–inference engines, and reinforcement learning systems. Currently focused on large‑scale LLM training, inference, and reinforcement learning system development.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=766ebc79f58b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Apache Fory Rust: A Versatile Serialization Framework for the Modern Age]]></title>
            <link>https://medium.com/@shawn.ck.yang/introducing-apache-fory-rust-a-versatile-serialization-framework-for-the-modern-age-8cfb701f73bf?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/8cfb701f73bf</guid>
            <category><![CDATA[rpc]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[rust]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Thu, 30 Oct 2025 17:03:34 GMT</pubDate>
            <atom:updated>2025-10-30T17:03:34.466Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>TL;DR</strong>: Apache Fory Rust is a blazingly-fast, cross-language serialization framework that delivers <strong>ultra-fast serialization performance</strong> while <strong>automatically handling circular references, trait objects, and schema evolution</strong>. Built with Rust’s safety guarantees and zero-copy techniques, it’s designed for developers who refuse to compromise between performance and developer experience.</p><ul><li>🐙 GitHub: <a href="https://github.com/apache/fory">https://github.com/apache/fory</a></li><li>📦 Crate: <a href="https://crates.io/crates/fory">https://crates.io/crates/fory</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UMV-XCrK19CkSmNB.png" /></figure><h3>The Serialization Dilemma</h3><p>Every backend engineer has faced this moment: your application needs to serialize complex data structures such as nested objects, circular references, polymorphic types, and you’re forced to choose between three bad options:</p><ol><li><strong>Fast but fragile</strong>: Hand-rolled binary formats that break with schema changes</li><li><strong>Flexible but slow</strong>: JSON/Protocol with 10x performance overhead</li><li><strong>Complex and limiting</strong>: Existing solutions that don’t support your language’s advanced features</li></ol><p>Apache Fory Rust eliminates this false choice. It’s a serialization framework that delivers exceptional performance while automatically handling the complexities of modern applications — no IDL files, no manual schema management, no compromises.</p><h3>What Makes Apache Fory Rust Different?</h3><h3>1. Truly Cross-Language</h3><p>Apache Fory Rust speaks the same binary protocol as Java, Python, C++, Go, and other language implementations. Serialize data in Rust, deserialize in Python — <strong>it just works</strong>. No schema files. No code generation. No version mismatches.</p><pre>// Rust: Serialize<br>let user = User {<br>    name: &quot;Alice&quot;.to_string(),<br>    age: 30,<br>    metadata: HashMap::from([(&quot;role&quot;, &quot;admin&quot;)]),<br>};<br>let bytes = fory.serialize(&amp;user);<br><br>// Python: Deserialize (same binary format!)<br>user = fory.deserialize(bytes)  # Just works!</pre><p>This isn’t just convenient — it changes how we develop microservices architectures where different teams use different languages.</p><h3>2. Automatic Shared/Circular Reference Handling</h3><p>Most serialization frameworks panic when encountering circular references. Apache Fory tracks and preserves reference identity automatically:</p><p><strong>Shared Reference</strong>:</p><pre>use fory::Fory;<br>use std::rc::Rc;<br><br>let fory = Fory::default();<br><br>// Create a shared value<br>let shared = Rc::new(String::from(&quot;shared_value&quot;));<br><br>// Reference it multiple times<br>let data = vec![shared.clone(), shared.clone(), shared.clone()];<br><br>// The shared value is serialized only once<br>let bytes = fory.serialize(&amp;data);<br>let decoded: Vec&lt;Rc&lt;String&gt;&gt; = fory.deserialize(&amp;bytes)?;<br><br>// Verify reference identity is preserved<br>assert_eq!(decoded.len(), 3);<br>assert_eq!(*decoded[0], &quot;shared_value&quot;);<br><br>// All three Rc pointers point to the same object<br>assert!(Rc::ptr_eq(&amp;decoded[0], &amp;decoded[1]));<br>assert!(Rc::ptr_eq(&amp;decoded[1], &amp;decoded[2]));</pre><p><strong>Circular Reference</strong>:</p><pre>use fory::{ForyObject, RcWeak};<br><br>#[derive(ForyObject)]<br>struct Node {<br>    value: i32,<br>    parent: RcWeak&lt;RefCell&lt;Node&gt;&gt;,     // Weak pointer breaks cycles<br>    children: Vec&lt;Rc&lt;RefCell&lt;Node&gt;&gt;&gt;,  // Strong references tracked<br>}<br><br>// Build a parent-child tree with circular references<br>let parent = Rc::new(RefCell::new(Node { ... }));<br>let child = Rc::new(RefCell::new(Node {<br>    parent: RcWeak::from(&amp;parent),  // Points back to parent<br>    ...<br>}));<br>parent.borrow_mut().children.push(child.clone());<br><br>// Serialization handles the cycle automatically<br>let bytes = fory.serialize(&amp;parent);<br>let decoded: Rc&lt;RefCell&lt;Node&gt;&gt; = fory.deserialize(&amp;bytes)?;<br><br>// Reference relationships preserved!<br>assert!(Rc::ptr_eq(&amp;decoded, &amp;decoded.borrow().children[0].borrow().parent.upgrade().unwrap()));</pre><p>This isn’t just a feature — it’s essential for graph databases, object-relational mappers, and domain models.</p><h3>3. Trait Object Serialization</h3><p>Rust’s trait system enables powerful abstractions, but serializing Box&lt;dyn Trait&gt; is notoriously difficult. Apache Fory makes it trivial:</p><pre>use fory::{ForyObject, Serializer, register_trait_type};<br>trait Animal: Serializer {<br>    fn speak(&amp;self) -&gt; String;<br>}<br>#[derive(ForyObject)]<br>struct Dog { name: String, breed: String }<br>#[derive(ForyObject)]<br>struct Cat { name: String, color: String }<br>// Register implementations<br>register_trait_type!(Animal, Dog, Cat);<br>// Serialize heterogeneous collections<br>let animals: Vec&lt;Box&lt;dyn Animal&gt;&gt; = vec![<br>    Box::new(Dog { ... }),<br>    Box::new(Cat { ... }),<br>];<br>let bytes = fory.serialize(&amp;animals);<br>let decoded: Vec&lt;Box&lt;dyn Animal&gt;&gt; = fory.deserialize(&amp;bytes)?;<br>// Polymorphism preserved!<br>decoded[0].speak();  // &quot;Woof!&quot;<br>decoded[1].speak();  // &quot;Meow!&quot;</pre><p><strong>Alternative: Using </strong><strong>dyn Any without trait registration</strong>:</p><pre>use std::rc::Rc;<br>use std::any::Any;<br>// No trait definition or registration needed<br>let dog: Rc&lt;dyn Any&gt; = Rc::new(Dog { name: &quot;Rex&quot;.to_string(), breed: &quot;Labrador&quot;.to_string() });<br>let cat: Rc&lt;dyn Any&gt; = Rc::new(Cat { name: &quot;Whiskers&quot;.to_string(), color: &quot;Orange&quot;.to_string() });<br>let bytes = fory.serialize(&amp;dog);<br>let decoded: Rc&lt;dyn Any&gt; = fory.deserialize(&amp;bytes)?;<br>// Downcast to concrete type<br>let unwrapped = decoded.downcast_ref::&lt;Dog&gt;().unwrap();<br>assert_eq!(unwrapped.name, &quot;Rex&quot;);</pre><p><strong>Supports</strong>:</p><ul><li>Box&lt;dyn Trait&gt; - Owned trait objects</li><li>Rc&lt;dyn Trait&gt; / Arc&lt;dyn Trait&gt; - Reference-counted trait objects</li><li>Rc&lt;dyn Any&gt; / Arc&lt;dyn Any&gt; - Runtime type dispatch without traits</li><li>Auto-generated wrapper types for standalone serialization</li></ul><p>This unlocks plugin systems, heterogeneous collections, and extensible architectures that were previously impossible to serialize.</p><h3>4. Schema Evolution Without Breaking Changes</h3><p>Microservices evolve independently. Apache Fory’s <strong>Compatible mode</strong> allows schema changes without coordination:</p><pre>use fory::{Fory, ForyObject};<br>// Service A: Version 1<br>#[derive(ForyObject)]<br>struct User {<br>    name: String,<br>    age: i32,<br>    address: String,<br>}<br>let mut fory_v1 = Fory::default().compatible(true);<br>fory_v1.register::&lt;User&gt;(1);<br>// Service B: Version 2 (evolved independently)<br>#[derive(ForyObject)]<br>struct User {<br>    name: String,<br>    age: i32,<br>    // address removed<br>    phone: Option&lt;String&gt;,     // New field<br>    metadata: HashMap&lt;String, String&gt;,  // Another new field<br>}<br>let mut fory_v2 = Fory::default().compatible(true);<br>fory_v2.register::&lt;User&gt;(1);<br>// V1 data deserializes into V2 structure<br>let v1_bytes = fory_v1.serialize(&amp;user_v1);<br>let user_v2: User = fory_v2.deserialize(&amp;v1_bytes)?;<br>// Missing fields get default values automatically</pre><p><strong>Compatibility rules</strong>:</p><ul><li>✅ Add new fields (default values applied)</li><li>✅ Remove fields (skipped during deserialization)</li><li>✅ Reorder fields (matched by name)</li><li>✅ Change nullability (T ↔ Option&lt;T&gt;)</li><li>❌ Type changes (except nullable variants)</li></ul><p>This is critical for zero-downtime deployments and polyglot microservices.</p><h3>The Technical Foundation</h3><h3>Protocol Design</h3><p>Apache Fory uses a sophisticated binary protocol designed for both performance and flexibility:</p><pre>| fory header | reference meta | type meta | value data |</pre><p><strong>Key innovations</strong>:</p><ol><li><strong>Efficient encoding</strong>: Variable-length integers, compact type IDs, bit-packed flags</li><li><strong>Reference tracking</strong>: Deduplicates shared objects automatically (serialize once, reference thereafter)</li><li><strong>Meta compression</strong>: Gzip compression for type metadata in meta-sharing mode</li><li><strong>Little-endian layout</strong>: Optimized for modern CPU architectures</li></ol><h3>Compile-Time Code Generation</h3><p>Unlike reflection-based frameworks, Apache Fory generates serialization code at compile time via procedural macros:</p><pre>use fory::ForyObject;<br>#[derive(ForyObject)]<br>struct Person {<br>    name: String,<br>    age: i32,<br>    address: Address,<br>}<br>// Macro generates:<br>// - fory_write_data() for serialization<br>// - fory_read_data() for deserialization<br>// - fory_reserved_space() for buffer pre-allocation<br>// - fory_get_type_id() for type registration</pre><p><strong>Benefits</strong>:</p><ul><li>⚡ <strong>Zero runtime overhead</strong>: No reflection, no vtable lookups</li><li>🛡️ <strong>Type safety</strong>: Compile-time errors instead of runtime panics</li><li>📦 <strong>Small binary size</strong>: Only code for types you actually use</li><li>🔍 <strong>IDE support</strong>: Full autocomplete and error checking</li></ul><h3>Architecture</h3><p>Apache Fory Rust consists of three focused crates:</p><pre>fory/            # High-level API<br>  └─ Convenience wrappers, derive re-exports<br>fory-core/       # Core serialization engine<br>  ├─ fory.rs         # Main entry point<br>  ├─ buffer.rs       # Zero-copy binary I/O<br>  ├─ serializer/     # Type-specific serializers<br>  ├─ resolver/       # Type registration &amp; dispatch<br>  ├─ meta/           # Meta string compression<br>  └─ row/            # Row format implementation<br>fory-derive/     # Procedural macros<br>  ├─ object/         # ForyObject derive macro<br>  └─ fory_row.rs    # ForyRow derive macro</pre><p>This modular design ensures clean separation of concerns and makes the codebase maintainable.</p><h3>Benchmarks: Real-World Performance</h3><p>With same compression ratio as Protobuf, but <strong>10x faster</strong>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*49yd4w8yHL2yYtis.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*whfHQe_MVPNfyE1w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xCm39_eml4bYuJFqis39nw.png" /></figure><h3>When to Use Apache Fory Rust</h3><h3>✅ Ideal Use Cases</h3><p><strong>1. Microservices with polyglot teams</strong></p><ul><li>Different services in different languages</li><li>Need seamless data exchange without schema files</li><li>Schema evolution across independent deployments</li></ul><p><strong>2. High-performance data pipelines</strong></p><ul><li>Processing millions of records per second</li><li>Memory-constrained environments (use row format)</li><li>Analytics workloads with selective field access</li></ul><p><strong>3. Complex domain models</strong></p><ul><li>Circular references (parent-child relationships, graphs)</li><li>Polymorphic types (trait objects, inheritance hierarchies)</li><li>Rich object graphs with shared references</li></ul><p><strong>4. Real-time systems</strong></p><ul><li>Low-latency requirements (&lt;1ms serialization)</li><li>Memory-mapped file access</li><li>Zero-copy deserialization critical</li></ul><h3>⚠️ Consider Alternatives If</h3><ol><li><strong>You need human-readable data</strong>: Use JSON/YAML for debugging</li><li><strong>You need long-term storage format</strong>: Use Parquet for data lakes</li><li><strong>Your data is trivial</strong>: serde + bincode is simpler for basic types</li></ol><h3>Getting Started in 5 Minutes</h3><h3>Installation</h3><p>Add to Cargo.toml:</p><pre>[dependencies]<br>fory = &quot;0.13&quot;</pre><h3>Basic Object Serialization</h3><pre>use fory::{Fory, Error, ForyObject};<br>#[derive(ForyObject, Debug, PartialEq)]<br>struct User {<br>    name: String,<br>    age: i32,<br>    email: String,<br>}<br>fn main() -&gt; Result&lt;(), Error&gt; {<br>    let mut fory = Fory::default();<br>    fory.register::&lt;User&gt;(1);  // Register with unique ID<br>    let user = User {<br>        name: &quot;Alice&quot;.to_string(),<br>        age: 30,<br>        email: &quot;alice@example.com&quot;.to_string(),<br>    };<br>    // Serialize<br>    let bytes = fory.serialize(&amp;user);<br>    // Deserialize<br>    let decoded: User = fory.deserialize(&amp;bytes)?;<br>    assert_eq!(user, decoded);<br>    Ok(())<br>}</pre><h3>Cross-Language Serialization</h3><pre>use fory::Fory;<br>// Enable cross-language mode<br>let mut fory = Fory::default().compatible(true).xlang(true);<br>// Register with id/namespace for cross-language compatibility<br>fory.register_by_namespace::&lt;User&gt;(1);<br>// fory.register_by_namespace::&lt;User&gt;(&quot;example&quot;, &quot;User&quot;);<br>let bytes = fory.serialize(&amp;user);<br>// This can now be deserialized in Java, Python, Go, etc.</pre><p>Register types with <strong>consistent IDs or names</strong> across all languages:</p><ul><li><strong>By ID</strong> (fory.register::&lt;User&gt;(1)): Faster serialization, more compact encoding, but requires coordination to avoid ID conflicts</li><li><strong>By name</strong> (fory.register_by_name::&lt;User&gt;(&quot;example.User&quot;)): More flexible, less prone to conflicts, easier to manage across teams, but slightly larger encoding</li></ul><h3>Supported Types</h3><p>Apache Fory Rust supports a comprehensive type system:</p><p><strong>Primitives</strong>: bool, i8, i16, i32, i64, f32, f64, String</p><p><strong>Collections</strong>: Vec&lt;T&gt;, HashMap&lt;K,V&gt;, BTreeMap&lt;K,V&gt;, HashSet&lt;T&gt;, Option&lt;T&gt;</p><p><strong>Smart Pointers</strong>: Box&lt;T&gt;, Rc&lt;T&gt;, Arc&lt;T&gt;, RcWeak&lt;T&gt;, ArcWeak&lt;T&gt;, RefCell&lt;T&gt;, Mutex&lt;T&gt;</p><p><strong>Date/Time</strong>: chrono::NaiveDate, chrono::NaiveDateTime</p><p><strong>Custom Types</strong>: Derive ForyObject for object graphs, ForyRow for row format</p><p><strong>Trait Objects</strong>: Box&lt;dyn T&gt;, Rc&lt;dyn T&gt;, Arc&lt;dyn T&gt;, Rc&lt;dyn Any&gt;, Arc&lt;dyn Any&gt;</p><h3>Roadmap: What’s Next</h3><p>Apache Fory Rust is production-ready today, but we’re just getting started and continuing active development:</p><h3>✅ Shipped in v0.13</h3><ul><li>✅ Static codegen via procedural macros</li><li>✅ Row format serialization with zero-copy</li><li>✅ Cross-language object graph serialization</li><li>✅ Shared and circular reference tracking</li><li>✅ Weak pointer support (RcWeak, ArcWeak)</li><li>✅ Trait object serialization (Box/Rc/Arc)</li><li>✅ Schema evolution in compatible mode</li></ul><h3>🚧 Coming Soon</h3><ul><li><strong>Cross-language reference serialization</strong>: serialize Rc/Arc to/from other languages.</li><li><strong>Partial row updates</strong>: Mutate row format in-place</li></ul><h3>🎯 Help Wanted</h3><p>We’re actively seeking contributors for:</p><ul><li><strong>Performance tuning</strong>: Profile and optimize hot paths</li><li><strong>Documentation</strong>: More examples, tutorials, and guides</li><li><strong>Testing</strong>: Fuzzing, property tests, edge case coverage</li></ul><h3>Production Considerations</h3><h3>Thread Safety</h3><p>Fory becomes fully thread-safe after registration is complete. Once every type is registered (which requires &amp;mut Fory), wrap the instance in an Arc and freely share it across worker threads for concurrent serialization and deserialization.</p><pre>use fory::Fory;<br>use std::{sync::Arc, thread};<br>let mut fory = Fory::default();<br>fory.register::&lt;Item&gt;(1)?;<br>let fory = Arc::new(fory); // `Fory` is Send + Sync once registration is done<br>let item = Item::default();<br>let handles: Vec&lt;_&gt; = (0..4)<br>    .map(|_| {<br>        let fory = Arc::clone(&amp;fory);<br>        let input = item.clone();<br>        thread::spawn(move || {<br>            let bytes = fory.serialize(&amp;input);<br>            let decoded: Item = fory.deserialize(&amp;bytes).expect(&quot;valid data&quot;);<br>            (bytes, decoded)<br>        })<br>    })<br>    .collect();<br>for handle in handles {<br>    let (bytes, decoded) = handle.join().expect(&quot;thread finished&quot;);<br>    // work with `bytes` / `decoded`<br>}</pre><h3>Error Handling</h3><p>Apache Fory uses Result&lt;T, Error&gt; for all fallible operations:</p><pre>use fory::Error;<br>match fory.deserialize::&lt;User&gt;(&amp;bytes) {<br>    Ok(user) =&gt; process_user(user),<br>    Err(Error::TypeMismatch) =&gt; log::error!(&quot;Schema mismatch&quot;),<br>    Err(Error::BufferTooShort) =&gt; log::error!(&quot;Incomplete data&quot;),<br>    Err(e) =&gt; log::error!(&quot;Deserialization failed: {}&quot;, e),<br>}</pre><h3>Documentation</h3><ul><li>Apache Fory Rust Guide: <a href="https://fory.apache.org/docs/docs/guide/rust_serialization">📖 View</a></li><li>Apache Fory Rust API Doc: <a href="https://docs.rs/fory/latest/fory/">📖 View</a></li><li>Apache Fory Xlang Serialization Spec: <a href="https://fory.apache.org/docs/specification/fory_xlang_serialization_spec/">📖 View</a></li></ul><h3>Community and Contribution</h3><p>Apache Fory is an <strong>Apache Software Foundation</strong> project with a vibrant, growing community:</p><ul><li><strong>GitHub</strong>: <a href="https://github.com/apache/fory">apache/fory</a></li><li><strong>Docs</strong>: <a href="https://fory.apache.org/">fory.apache.org</a></li><li><strong>Slack</strong>: <a href="https://join.slack.com/t/fory-project/shared_invite/zt-1u8soj4qc-ieYEu7ciHOqA2mo47llS8A">Join our community</a></li><li><strong>Issue Tracker</strong>: <a href="https://github.com/apache/fory/issues">GitHub Issues</a></li></ul><h3>How to Contribute</h3><p>We welcome contributions of all kinds:</p><ol><li><strong>Code</strong>: Implement features from the roadmap</li><li><strong>Docs</strong>: Write tutorials, examples, and guides</li><li><strong>Testing</strong>: Add benchmarks, fuzz tests, integration tests</li><li><strong>Feedback</strong>: Report bugs, request features, share use cases</li></ol><p>See <a href="https://github.com/apache/fory/blob/main/CONTRIBUTING.md">CONTRIBUTING.md</a> for guidelines.</p><h3>License</h3><p>Apache Fory is licensed under the <strong>Apache License 2.0</strong>, a permissive open-source license that allows commercial use, modification, and distribution.</p><h3>Conclusion</h3><p>Apache Fory Rust represents a paradigm shift in serialization:</p><ul><li><strong>No more trade-offs</strong>: Get performance <em>and</em> flexibility</li><li><strong>No more boilerplate</strong>: Derive macros handle the complexity</li><li><strong>No more lock-in</strong>: Trait-object and shared reference support by nature</li></ul><p>Whether you’re building microservices, data pipelines, or real-time systems, Apache Fory Rust delivers the performance you need with the ergonomics you deserve.</p><p><strong>Try it today</strong>:</p><pre>cargo add fory</pre><p><strong>Join the community</strong>:</p><pre>git clone https://github.com/apache/fory.git<br>cd fory/rust<br>cargo test --features tests</pre><p><strong>Share your experience</strong>:</p><ul><li>Write a blog post about your use case</li><li>Present at your local Rust meetup</li><li>Contribute benchmarks from your domain</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8cfb701f73bf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache Fury Serialization 0.8.0 released]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fury-serialization-0-8-0-released-9781362a5356?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/9781362a5356</guid>
            <category><![CDATA[graalvm]]></category>
            <category><![CDATA[serialization]]></category>
            <category><![CDATA[scala]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Tue, 08 Oct 2024 16:31:31 GMT</pubDate>
            <atom:updated>2024-10-08T16:31:31.721Z</atom:updated>
            <content:encoded><![CDATA[<p>The Apache Fury team is pleased to announce the 0.8.0 release. This is a major release that includes <a href="https://github.com/apache/fury/compare/v0.7.1...v0.8.0">23 PR</a> from 7 distinct contributors. See the <a href="https://fury.apache.org/docs/start/install">Install</a> Page to learn how to get the libraries for your platform.</p><h3>Highlights<a href="https://fury.apache.org/blog/fury_0_8_0_release#highlights">​</a></h3><ul><li>Support graalvm 17/21/22 native image</li><li>Release fury optimized serializers for scala collection</li><li>Reduce scala collection classname serialization cost using dict encoding</li></ul><h3>Features<a href="https://fury.apache.org/blog/fury_0_8_0_release#features">​</a></h3><ul><li>refactor(rust): simplify error handle by @jiacai2050 in <a href="https://github.com/apache/fury/pull/1823">https://github.com/apache/fury/pull/1823</a></li><li>feat(java): support graalvm 17/21/22 by @chaokunyang in <a href="https://github.com/apache/fury/pull/1845">https://github.com/apache/fury/pull/1845</a></li><li>perf(java): inline same element invoke in jit by @chaokunyang in <a href="https://github.com/apache/fury/pull/1851">https://github.com/apache/fury/pull/1851</a></li><li>perf(java): optimize read classdef perf by @chaokunyang in <a href="https://github.com/apache/fury/pull/1852">https://github.com/apache/fury/pull/1852</a></li><li>feat(scala): optimize scala class serialization by @chaokunyang in <a href="https://github.com/apache/fury/pull/1853">https://github.com/apache/fury/pull/1853</a></li><li>feat(java): implement sublist serializers by @chaokunyang in <a href="https://github.com/apache/fury/pull/1856">https://github.com/apache/fury/pull/1856</a></li><li>feat(java): use SubListViewSerializer only when tracking ref by @chaokunyang in <a href="https://github.com/apache/fury/pull/1858">https://github.com/apache/fury/pull/1858</a></li></ul><h3>Bug Fix<a href="https://fury.apache.org/blog/fury_0_8_0_release#bug-fix">​</a></h3><ul><li>fix(java): DeserializationException#getMessage call by @yoohaemin in <a href="https://github.com/apache/fury/pull/1830">https://github.com/apache/fury/pull/1830</a></li><li>fix(java): fix collection view serialization by @chaokunyang in <a href="https://github.com/apache/fury/pull/1833">https://github.com/apache/fury/pull/1833</a></li><li>fix(java): fix long type name meta string encoding by @chaokunyang in <a href="https://github.com/apache/fury/pull/1837">https://github.com/apache/fury/pull/1837</a></li><li>fix(java): fix serializer factory getSerializerClass by @chaokunyang in <a href="https://github.com/apache/fury/pull/1836">https://github.com/apache/fury/pull/1836</a></li><li>fix(rust): replace (value &lt;&lt; 8) | (value &gt;&gt; 8) with value.rotate_right(8) by @chaokunyang in <a href="https://github.com/apache/fury/pull/1841">https://github.com/apache/fury/pull/1841</a></li><li>fix(java): Fix for maximum size of java arrays by @fink-arthur in <a href="https://github.com/apache/fury/pull/1843">https://github.com/apache/fury/pull/1843</a></li><li>fix(java): Fix max Java array size for reader by @fink-arthur in <a href="https://github.com/apache/fury/pull/1844">https://github.com/apache/fury/pull/1844</a></li><li>fix(java): fix jdk proxy serialization when proxy writeReplace method by @chaokunyang in <a href="https://github.com/apache/fury/pull/1857">https://github.com/apache/fury/pull/1857</a></li></ul><h3>Other Improvements<a href="https://fury.apache.org/blog/fury_0_8_0_release#other-improvements">​</a></h3><ul><li>chore(java): fix default value doc for metaShareEnabled/scopedMetaShareEnabled by @chaokunyang in <a href="https://github.com/apache/fury/pull/1826">https://github.com/apache/fury/pull/1826</a></li><li>chore(doc): fix ‘how to upgrade fury’ link in README by @sh-cho in <a href="https://github.com/apache/fury/pull/1846">https://github.com/apache/fury/pull/1846</a></li><li>build(deps): bump com.google.protobuf:protobuf-java from 3.16.3 to 3.25.5 in /java/benchmark by @dependabot in <a href="https://github.com/apache/fury/pull/1847">https://github.com/apache/fury/pull/1847</a></li><li>chore(java): simplify generated codec name by @chaokunyang in <a href="https://github.com/apache/fury/pull/1850">https://github.com/apache/fury/pull/1850</a></li><li>ci: only run sync job if the repo is apache/fury by @pjfanning in <a href="https://github.com/apache/fury/pull/1860">https://github.com/apache/fury/pull/1860</a></li><li>feat(scala): upgrade sbt and sbt-apache-sonatype by @pjfanning in <a href="https://github.com/apache/fury/pull/1859">https://github.com/apache/fury/pull/1859</a></li></ul><h3>New Contributors<a href="https://fury.apache.org/blog/fury_0_8_0_release#new-contributors">​</a></h3><ul><li>@yoohaemin made their first contribution in <a href="https://github.com/apache/fury/pull/1830">https://github.com/apache/fury/pull/1830</a></li><li>@fink-arthur made their first contribution in <a href="https://github.com/apache/fury/pull/1843">https://github.com/apache/fury/pull/1843</a></li><li>@sh-cho made their first contribution in <a href="https://github.com/apache/fury/pull/1846">https://github.com/apache/fury/pull/1846</a></li></ul><p>Full Changelog: <a href="https://github.com/apache/fury/compare/v0.7.1...v0.8.0">https://github.com/apache/fury/compare/v0.7.1...v0.8.0</a></p><h3>Acknowledgements<a href="https://fury.apache.org/blog/fury_0_8_0_release#acknowledgements">​</a></h3><p>Thanks @@jiacai2050 @fink-arthur @sh-cho @pjfanning @chaokunyang @yoohaemin</p><p>A big thank you to all our contributors who have worked hard on this release. Your contributions, whether through code, documentation, or issue reporting, are really appreciated.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9781362a5356" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache Fury v0.7.1 Released]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fury-v0-7-1-released-fb89939a9233?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb89939a9233</guid>
            <category><![CDATA[feature-engineering]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[serialization]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Fri, 13 Sep 2024 16:50:37 GMT</pubDate>
            <atom:updated>2024-09-13T16:50:37.668Z</atom:updated>
            <content:encoded><![CDATA[<p>The Apache Fury team is pleased to announce the 0.7.1 release. This is a major release that includes <a href="https://github.com/apache/fury/compare/v0.7.0...v0.7.1">20 PR</a> from 8 distinct contributors. See the <a href="https://fury.apache.org/docs/start/install">Install</a> Page to learn how to get the libraries for your platform.</p><h3>Features<a href="https://fury.apache.org/blog/fury_0_7_1_release#features">​</a></h3><ul><li>feat(javascript): Added MetaString Class for Unicode Encoding/Decoding in Type.Object Code Generation by @Forchapeatl in <a href="https://github.com/apache/fury/pull/1774">https://github.com/apache/fury/pull/1774</a></li><li>feat(Rust): Refine Code Structure &amp; Prepare for Future Compatibility Features by @theweipeng in <a href="https://github.com/apache/fury/pull/1787">https://github.com/apache/fury/pull/1787</a></li><li>feat(java): ThreadSafeFury add getClassResolver method by @funky-eyes in <a href="https://github.com/apache/fury/pull/1780">https://github.com/apache/fury/pull/1780</a></li><li>feat(Rust): Implement TypeMeta part of the compatibility features by @theweipeng in <a href="https://github.com/apache/fury/pull/1789">https://github.com/apache/fury/pull/1789</a></li><li>feat(Rust): Support polymorphism by @theweipeng in <a href="https://github.com/apache/fury/pull/1795">https://github.com/apache/fury/pull/1795</a></li><li>feat(java): Support copy capabilities for some classes without no-argument constructors by @zhaommmmomo in <a href="https://github.com/apache/fury/pull/1794">https://github.com/apache/fury/pull/1794</a></li><li>feat(java): support jdk9+ java.util.ImmutableCollections copy by @zhaommmmomo in <a href="https://github.com/apache/fury/pull/1800">https://github.com/apache/fury/pull/1800</a></li><li>feat(rust): support enum serialization by @jiacai2050 in <a href="https://github.com/apache/fury/pull/1817">https://github.com/apache/fury/pull/1817</a></li><li>refine fury website and add chinese documents by @yuluo-yx and @LofiSu</li></ul><h3>Bug Fix<a href="https://fury.apache.org/blog/fury_0_7_1_release#bug-fix">​</a></h3><ul><li>ci: fix rust ci failed by @LiangliangSui in <a href="https://github.com/apache/fury/pull/1783">https://github.com/apache/fury/pull/1783</a></li><li>fix(java): fix classloader get npe by @chaokunyang in <a href="https://github.com/apache/fury/pull/1792">https://github.com/apache/fury/pull/1792</a></li><li>fix(scala): fix nested type serialization in scala object type by @chaokunyang in <a href="https://github.com/apache/fury/pull/1809">https://github.com/apache/fury/pull/1809</a></li><li>fix(java): Fix replace resolver serializaiton by @chaokunyang in <a href="https://github.com/apache/fury/pull/1812">https://github.com/apache/fury/pull/1812</a></li><li>fix(java): fix reserved keyword conflict by @chaokunyang in <a href="https://github.com/apache/fury/pull/1819">https://github.com/apache/fury/pull/1819</a></li><li>fix(java): fix nested map field value serialization by private map serializer by @chaokunyang in <a href="https://github.com/apache/fury/pull/1820">https://github.com/apache/fury/pull/1820</a></li><li>fix(rust): use iter to avoid reallocate by @jiacai2050 in <a href="https://github.com/apache/fury/pull/1821">https://github.com/apache/fury/pull/1821</a></li></ul><h3>Other Improvements<a href="https://fury.apache.org/blog/fury_0_7_1_release#other-improvements">​</a></h3><ul><li>chore(java): Disallow writing meta classdef when obj is null by @LiangliangSui in <a href="https://github.com/apache/fury/pull/1686">https://github.com/apache/fury/pull/1686</a></li><li>chore(infra): optimize github tmpl &amp; update actions/checkout version to 4.1.7 by @yuluo-yx in <a href="https://github.com/apache/fury/pull/1807">https://github.com/apache/fury/pull/1807</a></li><li>chore(infra): remove redundant bug reporting options by @yuluo-yx in <a href="https://github.com/apache/fury/pull/1810">https://github.com/apache/fury/pull/1810</a></li><li>docs: add check lint ci &amp; fix md lint by @yuluo-yx in <a href="https://github.com/apache/fury/pull/1811">https://github.com/apache/fury/pull/1811</a></li></ul><h3>New Contributors<a href="https://fury.apache.org/blog/fury_0_7_1_release#new-contributors">​</a></h3><ul><li>@Forchapeatl made their first contribution in <a href="https://github.com/apache/fury/pull/1774">https://github.com/apache/fury/pull/1774</a></li><li>@funky-eyes made their first contribution in <a href="https://github.com/apache/fury/pull/1780">https://github.com/apache/fury/pull/1780</a></li><li>@yuluo-yx made their first contribution in <a href="https://github.com/apache/fury/pull/1807">https://github.com/apache/fury/pull/1807</a></li></ul><p>Full Changelog: <a href="https://github.com/apache/fury/compare/v0.7.0...v0.7.1">https://github.com/apache/fury/compare/v0.7.0...v0.7.1</a></p><h3>Acknowledgements<a href="https://fury.apache.org/blog/fury_0_7_1_release#acknowledgements">​</a></h3><p>Thanks @jiacai2050 @chaokunyang @theweipeng @funky-eyes @Forchapeatl @zhaommmmomo @yuluo-yx @LiangliangSui @LofiSu</p><p>A big thank you to all our contributors who have worked hard on this release. Your contributions, whether through code, documentation, or issue reporting, are really appreciated.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb89939a9233" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache Fury 0.7.0 released: fast object deep cop]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fury-0-7-0-released-fast-object-deep-cop-bc4d6dcd3005?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/bc4d6dcd3005</guid>
            <category><![CDATA[serialization]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[deep-copy]]></category>
            <category><![CDATA[rpc]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Mon, 05 Aug 2024 11:20:09 GMT</pubDate>
            <atom:updated>2024-08-05T11:20:09.161Z</atom:updated>
            <content:encoded><![CDATA[<h3>Apache Fury 0.7.0 released: fast object deep copy support</h3><p>The Apache Fury team is pleased to announce the 0.6.0 release. This is a major release that includes <a href="https://github.com/apache/fury/compare/v0.6.0...v0.7.0">24 PR</a> from 7 distinct contributors. See the <a href="https://fury.apache.org/docs/start/install">Install</a> Page to learn how to get the libraries for your platform.</p><h3>High Light<a href="https://fury.apache.org/blog/fury_0_7_0_release#high-light">​</a></h3><h3>Experimental<a href="https://fury.apache.org/blog/fury_0_7_0_release#experimental">​</a></h3><p>Implement fast object deep copy framework for java:</p><pre>Fury fury = Fury.builder().withRefCopy(true).build();<br>fury.register(SomeClass.class);<br>SomeClass a = xxx;<br>SomeClass copied = fury.copy(a);</pre><pre>| Benchmark                     | objectType    | Score         | Error         | Units |<br>|-------------------------------|---------------|---------------|---------------|-------|<br>| fury_copy                     | MEDIA_CONTENT | 1243297.690   | ±  451828.452 | ops/s |<br>| fury_copy                     | SAMPLE        | 2670545.816   | ± 1378536.021 | ops/s |<br>| fury_copy                     | STRUCT        | 2673356.422   | ±  202288.322 | ops/s |<br>| fury_copy                     | STRUCT2       | 1943587.774   | ±  392513.707 | ops/s |<br>| fury_copy_int_map             | int map       | 1470264.733   | ± 1021875.257 | ops/s |<br>| fury_copy_list                | int list      | 3556892.276   | ±  127410.724 | ops/s |<br>| fury_copy_object_array        | array         | 4430589.112   | ±   25366.893 | ops/s |<br>| fury_copy_string_map          | string map    | 1736145.327   | ±  377806.877 | ops/s |<br>| kryo_copy                     | MEDIA_CONTENT | 804208.092    | ±   27429.069 | ops/s |<br>| kryo_copy                     | SAMPLE        | 717669.608    | ±   71093.370 | ops/s |<br>| kryo_copy                     | STRUCT        | 1076048.642   | ±  223194.146 | ops/s |<br>| kryo_copy                     | STRUCT2       | 141374.767    | ±   14150.535 | ops/s |<br>| kryo_copy_int_map             | int map       | 546203.187    | ±   54669.173 | ops/s |<br>| kryo_copy_list                | int list      | 843643.496    | ±  312306.921 | ops/s |<br>| kryo_copy_object_array        | object array  | 1593267.344   | ± 1721824.436 | ops/s |<br>| kryo_copy_string_map          | string map    | 574809.875    | ±   47316.340 | ops/s |</pre><ul><li>feat(Rust): add meta string encoding algorithm in Rust by @urlyy in <a href="https://github.com/apache/fury/pull/1712">https://github.com/apache/fury/pull/1712</a></li><li>feat(Rust): Implement utf16 to utf8 conversion algorithm by @urlyy in <a href="https://github.com/apache/fury/pull/1730">https://github.com/apache/fury/pull/1730</a></li><li>perf(java): add struct benchmark with pb by @chaokunyang in <a href="https://github.com/apache/fury/pull/1736">https://github.com/apache/fury/pull/1736</a></li><li>feat(java): fast object copy framework in fury java by @zhaommmmomo in <a href="https://github.com/apache/fury/pull/1701">https://github.com/apache/fury/pull/1701</a></li><li>perf(java): optimize pojo copy performance by @chaokunyang in <a href="https://github.com/apache/fury/pull/1739">https://github.com/apache/fury/pull/1739</a></li><li>feat(java): support jdk17+ record copy by @chaokunyang in <a href="https://github.com/apache/fury/pull/1741">https://github.com/apache/fury/pull/1741</a></li><li>feat(RUST): String detection is performed using SIMD techniques by @kitty-eu-org in <a href="https://github.com/apache/fury/pull/1752">https://github.com/apache/fury/pull/1752</a></li><li>feat(java): Add ‘Expose’ annotation to support “only de/serialize annotated fields” by @urlyy in <a href="https://github.com/apache/fury/pull/1751">https://github.com/apache/fury/pull/1751</a></li><li>feat(java): support Ignore inconsistent types deserialize by @weijiang157152688 in <a href="https://github.com/apache/fury/pull/1737">https://github.com/apache/fury/pull/1737</a></li><li>perf(java): optimize map copy perf by @chaokunyang in <a href="https://github.com/apache/fury/pull/1767">https://github.com/apache/fury/pull/1767</a></li><li>perf(java): optimize list copy perf by @chaokunyang in <a href="https://github.com/apache/fury/pull/1769">https://github.com/apache/fury/pull/1769</a></li><li>perf(java): optimize object array copy perf by @chaokunyang in <a href="https://github.com/apache/fury/pull/1770">https://github.com/apache/fury/pull/1770</a></li><li>feat(java): support deep ref copy by @chaokunyang in <a href="https://github.com/apache/fury/pull/1771">https://github.com/apache/fury/pull/1771</a></li></ul><h3>Bug Fix<a href="https://fury.apache.org/blog/fury_0_7_0_release#bug-fix">​</a></h3><ul><li>fix(java): fix janino commons classes issue by @chaokunyang in <a href="https://github.com/apache/fury/pull/1753">https://github.com/apache/fury/pull/1753</a></li><li>fix(scala): fix scala release version by @chaokunyang in <a href="https://github.com/apache/fury/pull/1756">https://github.com/apache/fury/pull/1756</a></li><li>fix(java): fix streaming classdef read by @chaokunyang in <a href="https://github.com/apache/fury/pull/1758">https://github.com/apache/fury/pull/1758</a></li><li>fix(java): fix big buffer streaming MetaShared read offset by @chaokunyang in <a href="https://github.com/apache/fury/pull/1760">https://github.com/apache/fury/pull/1760</a></li><li>fix(java): fix fury logger npe by @chaokunyang in <a href="https://github.com/apache/fury/pull/1762">https://github.com/apache/fury/pull/1762</a></li><li>fix(java): fix enum abstract field serialization by @chaokunyang in <a href="https://github.com/apache/fury/pull/1765">https://github.com/apache/fury/pull/1765</a></li><li>fix(java): Fix memory leak in StructSerializer.xread() caused by re-pushing instead of popping GenericType. by @komamitsu in <a href="https://github.com/apache/fury/pull/1768">https://github.com/apache/fury/pull/1768</a></li></ul><h3>Other Improvements<a href="https://fury.apache.org/blog/fury_0_7_0_release#other-improvements">​</a></h3><ul><li>chore: Update case in DISCLAIMER by @pjfanning in <a href="https://github.com/apache/fury/pull/1746">https://github.com/apache/fury/pull/1746</a></li><li>chore: bump dev version to 0.7.0 by @chaokunyang in <a href="https://github.com/apache/fury/pull/1755">https://github.com/apache/fury/pull/1755</a></li><li>chore(java): rename copyTrackingRef to copyRef by @chaokunyang in <a href="https://github.com/apache/fury/pull/1748">https://github.com/apache/fury/pull/1748</a></li><li>chore(java): add fury deep copy documentation by @chaokunyang in <a href="https://github.com/apache/fury/pull/1773">https://github.com/apache/fury/pull/1773</a></li></ul><h3>New Contributors<a href="https://fury.apache.org/blog/fury_0_7_0_release#new-contributors">​</a></h3><ul><li>@urlyy made their first contribution in <a href="https://github.com/apache/fury/pull/1712">https://github.com/apache/fury/pull/1712</a></li><li>@zhaommmmomo made their first contribution in <a href="https://github.com/apache/fury/pull/1701">https://github.com/apache/fury/pull/1701</a></li><li>@kitty-eu-org made their first contribution in <a href="https://github.com/apache/fury/pull/1752">https://github.com/apache/fury/pull/1752</a></li><li>@komamitsu made their first contribution in <a href="https://github.com/apache/fury/pull/1768">https://github.com/apache/fury/pull/1768</a></li></ul><p>Full Changelog: <a href="https://github.com/apache/fury/compare/v0.6.0...v0.7.0">https://github.com/apache/fury/compare/v0.6.0...v0.7.0</a></p><h3>Acknowledgements<a href="https://fury.apache.org/blog/fury_0_7_0_release#acknowledgements">​</a></h3><p>Thanks @komamitsu @pjfanning @chaokunyang @weijiang157152688 @kitty-eu-org @urlyy @zhaommmmomo A big thank you to all our contributors who have worked hard on this release. Your contributions, whether through code, documentation, or issue reporting, are really appreciated.</p><p>Full Changelog: <a href="https://github.com/apache/fury/compare/v0.6.0...v0.7.0">https://github.com/apache/fury/compare/v0.6.0...v0.7.0</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bc4d6dcd3005" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Apache Fury 0.6.0 Released: 4x faster and 1/2 smaller than Protobuf]]></title>
            <link>https://medium.com/@shawn.ck.yang/apache-fury-0-6-0-released-4x-faster-and-1-2-smaller-than-protobuf-24f470b27513?source=rss-c54c340fa1bb------2</link>
            <guid isPermaLink="false">https://medium.com/p/24f470b27513</guid>
            <category><![CDATA[distributed-systems]]></category>
            <category><![CDATA[big-data]]></category>
            <category><![CDATA[java]]></category>
            <category><![CDATA[performance]]></category>
            <category><![CDATA[serialization]]></category>
            <dc:creator><![CDATA[Shawn.Yang]]></dc:creator>
            <pubDate>Wed, 24 Jul 2024 12:48:06 GMT</pubDate>
            <atom:updated>2024-07-24T12:48:06.891Z</atom:updated>
            <content:encoded><![CDATA[<p>The Apache Fury team is pleased to announce the 0.6.0 release. This is a major release that includes <a href="https://github.com/apache/fury/compare/v0.5.1...v0.6.0">35 PR</a> from 12 distinct contributors. See the <a href="https://fury.apache.org/docs/start/install">Install</a> Page to learn how to get the libraries for your platform.</p><h3>High light<a href="https://fury.apache.org/blog#high-light">​</a></h3><p>In this release, we introduced a scoped meta share mode for schema evolution in java and enabled it by default when CompatibleMode is set to Compatible:</p><ul><li>This mode is 50% faster than previous KV compatible mode, and only 1/6 size of serialized payload than before.</li><li>It’s 4x faster than protobuf, less than 1/2 serialized size of protobuf for complex object.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DrWFrGuxnBZpjGal.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/635/0*FFi9L5S6_0ZGA73k.png" /></figure><p>Protobuf/JSON will write message fields meta and values in a KV layout, so when serializzing a list of message, they will have two issues:</p><ul><li>Write meta multiple times even those message are the same type.</li><li>KV layout is dispersive, which is not friendly for compression.</li></ul><p>The meta share mode will write field name&amp;type meta of a struct only once for multiple objects of same type, which will save space and improve performance comparedto protobuf.</p><p>With meta share, we can write field name&amp;type meta of a struct only once for multiple objects of same type, which will save space and improve performance comparedto protobuf. And we can also encode the meta into binary in advance, and use one memory copy to write it which will be much faster.</p><h3>Serialize data<a href="https://fury.apache.org/blog#serialize-data">​</a></h3><pre>  public static class NumericStruct {<br>    public int f1;<br>    public int f2;<br>    public int f3;<br>    public int f4;<br>    public int f5;<br>    public int f6;<br>    public int f7;<br>    public int f8;<br><br>    public static NumericStruct build() {<br>      NumericStruct struct = new NumericStruct();<br>      struct.f1 = 1;<br>      struct.f2 = 2;<br>      struct.f3 = 3;<br>      struct.f4 = 4;<br>      struct.f5 = 5;<br>      struct.f6 = 6;<br>      struct.f7 = 7;<br>      struct.f8 = 8;<br>      return struct;<br>    }<br>  }<br><br>  public static class NumericStructList {<br>    public List&lt;NumericStruct&gt; list;<br><br>    public static NumericStructList build() {<br>      NumericStructList structList = new NumericStructList();<br>      structList.list = new ArrayList&lt;&gt;(1000);<br>      for (int i = 0; i &lt; 1000; i++) {<br>        structList.list.add(NumericStruct.build());<br>      }<br>      return structList;<br>    }<br>}</pre><p>Performance:</p><pre>Benchmark                       Mode  Cnt      Score      Error  Units<br>fury_deserialize                thrpt   30  49667.900 ± 3004.061  ops/s<br>fury_kv_compatible_deserialize  thrpt   30  33014.595 ± 3716.199  ops/s<br>fury_kv_compatible_serialize    thrpt   30  23915.260 ± 3968.119  ops/s<br>fury_serialize                  thrpt   30  63146.826 ± 2930.505  ops/s<br>protobuf_deserialize            thrpt   30  14156.610 ±  685.272  ops/s<br>protobuf_serialize              thrpt   30  10060.293 ±  706.064  ops/s</pre><p>Size:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/612/1*G4okV3mGbyaY5F6DZCuuOQ.png" /></figure><h3>Feature<a href="https://fury.apache.org/blog#feature">​</a></h3><ul><li>feat(java): support nonexistent class deserialization in meta share mode by @chaokunyang in <a href="https://github.com/apache/fury/pull/1646">https://github.com/apache/fury/pull/1646</a></li><li>feat(java): scoped meta share mode for type forward/backward compaibility by @chaokunyang in <a href="https://github.com/apache/fury/pull/1660">https://github.com/apache/fury/pull/1660</a></li><li>feat(java): support meta compression by Deflater by @chaokunyang in <a href="https://github.com/apache/fury/pull/1663">https://github.com/apache/fury/pull/1663</a></li><li>perf(java): Add ClassInfo ClassBytes generation conditions. by @LiangliangSui in <a href="https://github.com/apache/fury/pull/1667">https://github.com/apache/fury/pull/1667</a></li><li>feat(javascript): use TextDecoder to decode buffer by @bytemain in <a href="https://github.com/apache/fury/pull/1699">https://github.com/apache/fury/pull/1699</a></li><li>feat(Python): meta string encoding algorithm in Python by @pandalee99 in <a href="https://github.com/apache/fury/pull/1702">https://github.com/apache/fury/pull/1702</a></li><li>feat(C++): String detection is performed using SIMD techniques by @pandalee99 in <a href="https://github.com/apache/fury/pull/1720">https://github.com/apache/fury/pull/1720</a></li><li>feat(C++): The use of SIMD accelerated to implement and optimize utf16 utf8 by @pandalee99 in <a href="https://github.com/apache/fury/pull/1732">https://github.com/apache/fury/pull/1732</a></li><li>feat(java): enable scoped meta share for compatible mode by default by @chaokunyang in <a href="https://github.com/apache/fury/pull/1733">https://github.com/apache/fury/pull/1733</a></li><li>perf(java): optimize scoped meta share mode perf by @chaokunyang in <a href="https://github.com/apache/fury/pull/1734">https://github.com/apache/fury/pull/1734</a></li></ul><h3>Bug Fix<a href="https://fury.apache.org/blog#bug-fix">​</a></h3><ul><li>chore(doc): fix example by @wangjie-fourth in <a href="https://github.com/apache/fury/pull/1657">https://github.com/apache/fury/pull/1657</a></li><li>fix(java): fix scala object type codegen by @chaokunyang in <a href="https://github.com/apache/fury/pull/1659">https://github.com/apache/fury/pull/1659</a></li><li>fix(java): Fix header offset issue in MetaStringBytes hashcode by @LiangliangSui in <a href="https://github.com/apache/fury/pull/1668">https://github.com/apache/fury/pull/1668</a></li><li>fix(java): return fury to pooled which get from by @MrChang0 in <a href="https://github.com/apache/fury/pull/1697">https://github.com/apache/fury/pull/1697</a></li><li>fix(doc): codestyle version in python by @pandalee99 in <a href="https://github.com/apache/fury/pull/1706">https://github.com/apache/fury/pull/1706</a></li><li>fix(java): fix nested map serialization codegen by @chaokunyang in <a href="https://github.com/apache/fury/pull/1713">https://github.com/apache/fury/pull/1713</a></li><li>fix(java): fix fastjson object serialization by @chaokunyang in <a href="https://github.com/apache/fury/pull/1717">https://github.com/apache/fury/pull/1717</a></li></ul><h3>Others<a href="https://fury.apache.org/blog#others">​</a></h3><ul><li>chore: Add IssueNavigationLink and icon for IDEA by @lvshaokang in <a href="https://github.com/apache/fury/pull/1665">https://github.com/apache/fury/pull/1665</a></li><li>chore(rust): resolve deprecate warnings by @waynexia in <a href="https://github.com/apache/fury/pull/1662">https://github.com/apache/fury/pull/1662</a></li><li>chore(doc): fix doc example code by @wangjie-fourth in <a href="https://github.com/apache/fury/pull/1666">https://github.com/apache/fury/pull/1666</a></li><li>chore(rust): Setup rustfmt and toolchain for rust by @Xuanwo in <a href="https://github.com/apache/fury/pull/1677">https://github.com/apache/fury/pull/1677</a></li><li>chore(rust): Make rust clippy happy by @Xuanwo in <a href="https://github.com/apache/fury/pull/1678">https://github.com/apache/fury/pull/1678</a></li><li>chore(doc): add incubating DISCLAIMER by @chaokunyang in <a href="https://github.com/apache/fury/pull/1681">https://github.com/apache/fury/pull/1681</a></li><li>chore(java): Update github URL in IntelliJ vcs.xml by @pjfanning in <a href="https://github.com/apache/fury/pull/1689">https://github.com/apache/fury/pull/1689</a></li><li>ci: fix ci error by @LiangliangSui in <a href="https://github.com/apache/fury/pull/1691">https://github.com/apache/fury/pull/1691</a></li><li>docs: fix badge x by @vesense in <a href="https://github.com/apache/fury/pull/1694">https://github.com/apache/fury/pull/1694</a></li><li>chore(doc): fix compiler error by @wangjie-fourth in <a href="https://github.com/apache/fury/pull/1698">https://github.com/apache/fury/pull/1698</a></li><li>refactor(java): move latin language checker method from string serializer to string util by @anagh07 in <a href="https://github.com/apache/fury/pull/1708">https://github.com/apache/fury/pull/1708</a></li><li>chore(doc): the more complete readme is in python by @pandalee99 in <a href="https://github.com/apache/fury/pull/1709">https://github.com/apache/fury/pull/1709</a></li><li>build: update scala build by @pjfanning in <a href="https://github.com/apache/fury/pull/1725">https://github.com/apache/fury/pull/1725</a></li><li>build: publish jars for fury-scala by @pjfanning in <a href="https://github.com/apache/fury/pull/1729">https://github.com/apache/fury/pull/1729</a></li><li>chore(java): merge reflect.Types into TypeRef by @chaokunyang in <a href="https://github.com/apache/fury/pull/1731">https://github.com/apache/fury/pull/1731</a></li></ul><h3>New Contributors<a href="https://fury.apache.org/blog#new-contributors">​</a></h3><ul><li>@wangjie-fourth made their first contribution in <a href="https://github.com/apache/fury/pull/1657">https://github.com/apache/fury/pull/1657</a></li><li>@lvshaokang made their first contribution in <a href="https://github.com/apache/fury/pull/1665">https://github.com/apache/fury/pull/1665</a></li><li>@waynexia made their first contribution in <a href="https://github.com/apache/fury/pull/1662">https://github.com/apache/fury/pull/1662</a></li><li>@Xuanwo made their first contribution in <a href="https://github.com/apache/fury/pull/1677">https://github.com/apache/fury/pull/1677</a></li><li>@anagh07 made their first contribution in <a href="https://github.com/apache/fury/pull/1708">https://github.com/apache/fury/pull/1708</a></li></ul><p>Full Changelog: <a href="https://github.com/apache/fury/compare/v0.5.1...v0.6.0">https://github.com/apache/fury/compare/v0.5.1...v0.6.0</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=24f470b27513" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>