9 ms·
Fury – Fast multi-language serialization framework powered by JIT and Zero-copy
- chaokunyang 3y agoFury is also the fastest jvm serialization framework in the https://github.com/eishay/jvm-serializers/wiki https://github.com/eishay/jvm-serializers/wiki
- marginalia_nu 3y agoWeird they aren't emphasizing competitiveness with Protobuf and Avro, which is what I'd look at long before java serialization if I wanted fast object serialization.
- chaokunyang 3y agoProtobuf/Avro doesn't support polymorphism and circular references, maybe that's one of thge reason? But even compared with protobuf, fury is 3.2x faster. When comparing with avro, fury is 5.3x faster
- TeeWEE 3y agoHow can this be faster than Protobuf? Protobuf basically does a direct storage of bytestream to memory. No parsing needed because it precompiled the stubs. Theoretically it can’t be much faster. And having an IDL is an advantage imho. Clear specs and interface design.
- chaokunyang 3y agoNot exactly. Protobuf has compression for string/numbers. Fury use different compression protocol. Another thing is that Protobuf generated code are not efficient enough. Fury generated the code at runtime, which has more information about the jvm, then it can genereate more eifficient code, avoid many memory access, branchs, and do more code optimization.
- chaokunyang 3y agoSee https://medium.com/@shawn.ck.yang/fury-a-blazing-fast-multi-language-serialization-framework-powered-by-jit-and-zero-copy-fdd16f3215cb https://medium.com/@shawn.ck.yang/fury-a-blazing-fast-multi-... for fury implementation details
- usrusr 3y agoJust imagine the project landscape you'd need to be in to consider starting this worthwhile, given all uncertainty of success and so on. Or a very large middle finger to YAGNI, but I doubt it's that.
- chaokunyang 3y agoGood point! The success of a project is not only determined by what it can do, but more determined by what it chooses not to do. Only with clear and simple goals can we focus on what truly matters, while also attracting more developers to join our community.
- chaokunyang 3y agoBut I want to say that Fury will be continuously maintained. I created it 4 years ago, open sourced it in 2023.07. I've maintained it with little credits for 4 years. Now with it open-sourced, it will just make me put more efforts on it. But on the other hand, the success of fury does not depend on whether I put in enough effort but on whether I can build a thriving community to involve more people to join us. I must admit that I am still learning in this area and have a long way to go.
- hardwaresofton 3y agoBeware of burnout -- if companies take you at your word and expect continuous maintenance (for free), the load might be hard to bear after a while. The best way to avoid it I know of is to delegate responsibility and find other people to maintain the library with you (and/or charge for development/encourage corporate sponsorships!)
- chaokunyang 3y agoThanks for your kind words. I also want to find more people to join us tro maintain the library. But I still don't know how to involve more people to join the fury community.
- 3y ago
- egamirorrim 3y agoOOI, in a 'modern' app, what would you be using this kind of serialisation and deserialisation for? Some kind of complex RPC?
- deleted 3y ago[deleted]
- chaokunyang 3y agoThere are 3 kinds of scenarios are serialization bounded: 1. RPC for large microservices application, which are latency&throughput sensitive. The domain model can be huge, serialization will be the bottleneck. Some domain object graph may contains thousands of objects, serializing using jdk will take seconds, and the serialization result may be 50~100kb. Take Order as an example, imagine you need to process an order which has 500 items. 2. Data transfer for bigdata distributed systems: bigdata systems will handle much data, the data needs be transfered between workers. The serialization can be the bottleneck too. Spark RDD,Flink DataStream all have this bottleneck. The use bianry format such as arrow/tungsten format to reduce serialization overhead. But it's limited, sql oritiened, and can't express complex logic such as graph/event/domain. 3. Task scheduling: Image you have a mpp distributed systems, you need to schedule thounds of tasks in a process every sub-seconds. Serialization will be the bottleneck too.
- specialist 3y agoYes and: Kyro was motivated by building multi player games.
- chaokunyang 3y agoYes, Game is another scenario, it's very latency sensitive. Fury is very suitable too. Actually the java implememtation has been featured by some game developers. And there has always been a demand within the community for FURY to support C#: https://github.com/alipay/fury/issues/686 https://github.com/alipay/fury/issues/686 . I don't have experience for c#, so it's not supported. Hope c# can be supported with the help of the community
- npstr 3y agoThe comparison to JDK serialization is surprising me. Noone should be using it for anything serious in production. Even the Chief Architect of the Java platform has called it a "horrible mistake". https://www.infoworld.com/article/3275924/oracle-plans-to-dump-risky-java-serialization.html https://www.infoworld.com/article/3275924/oracle-plans-to-du...
- chaokunyang 3y agoThere are too many java serialization libraries, I compared fury with jdk/kryo/fst/protostuff/protobuf/flatbuffers/thrift/msgpack/canproto/acro/jackson/json. Fury are fastest too. See https://github.com/eishay/jvm-serializers/wiki https://github.com/eishay/jvm-serializers/wiki for detailed benchmark results. It's a hard choice to select one for the title, so I use JDK for it, which may be not a good choice. BTW, fury support jit serialization for jdk17 record, which is super fast compared to other serialization frameworks such as kryo
- pron 3y agoJust to be clear, though, the mistake that Mark Reinhold refers to isn't the particular implementation of the JDK's core serialization, but the design that allows arbitrary objects to be deserialized while bypassing their constructors (and so their established invariants). Unfortunately, many other serialization libraries — faster or slower — are repeating the same mistake. I.e., any serialization library that can serialize any class that implements Serializable suffers from all the same flaws of core serialization. Correct serialization can only be done for classes that are designed for it by having a well-known construction protocol, which are currently basic collections, enums, Strings, records, and classes that register specific serialization code.
- chaokunyang 3y agoI see, totally agreed! If any objects can be serialized, the deserialization will introduce security issue too. For example, `constructor/equals/hashCode` may contains malicious code, which introduce the deserialization risks. Fury put much work on this to avoid the open dynamic deserialization risks. But although `basic collections, enums, Strings, records, and classes that register specific serialization code` are the only objects should be allowed for serialization, and they are serialized by the construction protocol in fury already. There are so many applications has used the existing serialization protocol assumption, we have to keep compatible, otherwise most of application can't use fury.
- jarym 3y agoI wonder how this compares with Microstream One which looked to have quite slick serialisation capabilities
- chaokunyang 3y agoI benchmarked with Microstream using jmh and jvm-serializers data. Hare are the results: 1) fury is 43x faster for the speed. 2) Fury is 5x smaller for serialized binary size Here is the code for reproduction: https://github.com/chaokunyang/fury-benchmarks#fury-vs-microstream https://github.com/chaokunyang/fury-benchmarks#fury-vs-micro...
- vlovich123 3y agoHow does Fury compare to static schema serialization frameworks that aren’t Java focused? For example, flat buffers, alkahest, protobuf etc.
- chaokunyang 3y agoCompared with protobuf, fury is 3.2x faster. When comparing with avro, fury is 5.3x faster. Compared with flatbuffers, fury is 4.8x faster. See https://github.com/eishay/jvm-serializers/wiki https://github.com/eishay/jvm-serializers/wiki for detailed benchmark data
- vlovich123 3y ago* on the JVM Right? Flatbuffers supposedly being slower than protobufs is circumspect since most benchmarks I’ve seen for it in C++/Rust show it outperforming, especially since it too does zero-copy deser.
- chaokunyang 3y agoYes, on the jvm. Haven't tested it for native languages, C++/Rust should be faster since it doesn't compress data and it's zero-copy
- arnold_palmur 3y agoNo comparisons to SBE in the benchmarks?
- chaokunyang 3y agoSBE needs to define the xml for the java bean, and generated the code. It need lots of work to implement a multiple-layer nested objects serialization. So I don't added it for now.
- belfthrow 3y agoShould still be added. Are are talking a lot about perfomance so this is where SBE shines. Worth comparing if you want to show of the numbers.
- chaokunyang 3y agoNo, I just mean it's not easy to use. When using fury, you just need one line code for serialization: `fury.serialize(javaObject)`. When using SBE, it need to much coding, it needs define schema xml, compile code, and so on.
- belfthrow 3y agoIt's as much work as protobuf. How about Chronicle Wire, can you add that?
- fakecrusade 3y agoInteresting, I work in the same company but have never heard of it
- chaokunyang 3y agohaha, maybe it's time to use it now. It's used wisely in distributed systems at our company. I posted several blogs in our internal ata bbs, you can search it
- SpaghettiCthulu 3y agoI'm curious, why do you appear to generate and compile Java source code at runtime instead of generating bytecode directly or using `MethodHandle`s?
- chaokunyang 3y agoGood question! Part of code are generated using `MethodHandle` such as some field getters, or constructor. But the overall code are generated as source code first at runtime instead of bytecode. This is because binary protocol are very complicated. Generated the bytecode directly will make the troubleshooting more difficult. but it's possible to generated the bytecode techniquely. We have an IR abstraction, it's possible to change it to generate the bytecode
- aardvark179 3y agoThe danger with generating source code is that you now depend on source rules which may have changed, never applied to your source language, or are made more complicated by class loading refs. I’d definitely go for byte code generation, and possibly using constant dynamic to handle any really tricky constants, over source code any day.
- SpaghettiCthulu 3y agoI would go for `MethodHandle`s and lambda metafactory over bytecode where possible. Much easier to avoid and debug bugs in the generation (better errors than those provided by Hotspot's verifier), and avoids needing to worry about constant dynamic at all. Of course, once you need to implement more than one method, you can no longer just use lambda metafactory. A while back I actually implemented some utilities for generating classes at runtime and "linking" constants into them using constant dynamic. One day I might clean it up and release it as a library.
- chaokunyang 3y agoGood point, I used `lambda metafactory` too in fury, but only for some `constructor/getters`. I implements some Function utils to generate lambda function, see https://github.com/alipay/fury/blob/main/java/fury-core/src/main/java/io/fury/util/function/Functions.java https://github.com/alipay/fury/blob/main/java/fury-core/src/... I'm not sure whether `MethodHandle` can generate the most complicated code, since the serialization logic here are more complicated even than the manual written code.
- gigatexal 3y agocan someone help a noob like me understand where i would use something like this? is this a way to get faster json parsing?
- chaokunyang 3y agoJson doesn't support polymorphism and circular/shared references, those scenarios are more suitable for fury. And json is a text protocol, which is inefficient compared to fury binary protocol. Taking jackson json lib as an example: 1) Fury is 41.6x faster than jackson for Struct serialization 2) Fury is 65.6x faster than jackson for Struct deserialization 3) Fury is 9.4x faster than jackson for MediaContent serialization 4) Fury is 9.6x faster than jackson for MediaContent deserialization For http rest api, json is more suitable. For RPC/bigdata/game/scheduling, fury may be better
- gigatexal 3y agoThank you chao!
- chaokunyang 3y agoAnother issue for json format is that it will bloat the payload. For example, for an int `1111122222` will take 10 bytes in json, but only 4 bytes in fury. `0.3333333333333333` will need 18 bytes in json, but only 4 bytes in fury.
- Game_Ender 3y agoTwo questions: - Does Fury support versioning? - What is source of truth for the schema when dealing with multiple languages and the same data?
- chaokunyang 3y agoGood questions. 1)Fury support versions. 2) The schema will be included in the data, and will be used for deserializing/validating the data. The schema will be sent to peer once for a tpc connection.
- RantyDave 3y agoGreat that it's fast - but I'm not sure it would make all that much difference in Python code.
- chaokunyang 3y agoFor python, the speedup won't be so huge, we get a 50%~100% speed up for dataclasses. We haven't put much efforts on it. In future I believe the speed up will be larger.
- knutwannheden 3y agoInteresting. I will be curious to see how it stacks up against Jackson Smile, both in terms of features and performance. Since it appears to support both polymorphism and back-references, it looks like it already has some advanced features.
- chaokunyang 3y agoYeah, you are right. Fury supports polymorphism and circular/shared references, which are not supported by json/jackson. I did a benchmark with jackson before, here are the results: 1) Fury is 41.6x faster than jackson for Struct serialization 2) Fury is 65.6x faster than jackson for Struct deserialization 3) Fury is 9.4x faster than jackson for MediaContent serialization 4) Fury is 9.6x faster than jackson for MediaContent deserialization see https://github.com/chaokunyang/fury-benchmarks https://github.com/chaokunyang/fury-benchmarks for detailed benchmark code.
- chaokunyang 3y agoAnother issue about json is that json is not storage efficient. For a float 0.3333333333333335, json needs 18 bytes, but fury needs only 4 bytes.