MicroStream(反序列化)如何工作? - java

我想知道MicroStream的序列化如何工作。
由于它被描述为“超快”,因此必须依靠代码生成,对吗?还是基于反思?
与Protobuf-Serialization相比,它的性能如何?Protobuf-Serialization依赖于直接从java字段中读取并将其写入字节缓冲区的Code-generation,反之亦然。
在大范围串行化对象时,使用反射会大大降低性能,不是吗?

我正在寻找一种快速的方法来为多人游戏传输和持久存储对象,并且每一毫秒都很重要。 🙂

提前致谢!

PS:由于我的信誉不高,因此无法创建“微流”标签。 https://microstream.one/

参考方案

我是MicroStream的首席开发人员。
(这不是别名帐户。我确实是创建它的。我在StackOverflow上阅读了10年左右,但从未有过创建帐户的理由。直到现在。)

在每次初始化时,MicroStream都会分析所有必需实体和值类型类的当前运行时版本,并从中获取优化的元数据。
在运行时遇到迄今为止尚不了解的类时,将执行相同的操作。
分析是针对每个反射进行的,但是由于对于每个处理的类仅进行一次分析,因此反射性能成本可以忽略不计。
实际的存储和加载或序列化和反序列化是基于创建的元数据通过优化的框架代码完成的。

如果类布局发生更改,则类型分析将从存储该类实例的字段布局创建映射到当前类的映射。
如有可能,自动进行(明确的更改或通过一些可配置的试探法),否则通过用户提供的映射。性能保持不变,因为JVM不在乎它(简而言之)是否将加载的值3复制到位置3或位置5。全部在元数据中。

使用了ByteBuffer,更精确地说是直接使用ByteBuffer,但仅用作通过直接“不安全”低级操作来处理堆外内存的锚点。如果您不熟悉“不安全”操作,那么一个简短而简单的概念就是:“它与C ++代码一样直接和快速。”您可以非常快地完成几乎所有需要的操作,但是您也要对所有事情负责。有关更多详细信息,请谷歌“ sun.misc.Unsafe”。

没有代码生成。没有使用字节码黑客攻击,通过代理或类似的猴子业务默认替换实例。从技术上讲,它只是一个Java库(包括“不安全”用法),但具有许多经过适当设计的逻辑。

附带说明:反射速度不像通常认为的那样慢。不再。确实如此,但是在过去的Java版本中已经对其进行了很多优化。
只有每项操作都必须重新进行所有的类分析,字段查找等操作时,它才很慢(很多框架似乎都做得不好,因为它们写得不好)。如果一次收集(设置可访问性等)字段然后将其缓存,则反射实际上出奇地快。

关于与Protobuf序列化的比较:

由于我没有使用过协议缓冲区,而且我不知道它在内部如何工作,因此我无法透露任何具体信息。
与复杂技术一样,由于不同的技术具有不同的优化优先级和限制,因此很难进行真正有意义的比较。

大多数序列化方法都放弃了引用一致性,但只存储“数据”(即,如果两个对象引用了第三个对象,则反序列化将创建该第三个对象的两个实例。
这样:A-> C A-> C1 B-> C2。
基本上,这会破坏/破坏/破坏对象图,并使循环图的序列化成为不可能,因为它会创建并无限级联复制。例如,请参阅JSON序列化。有趣的事。)
甚至Brian Goetz的Java“ Serialization 2.0”草案也包含该限制(请参阅http://cr.openjdk.java.net/~briangoetz/amber/serialization.html的“限制”)(以及另一个打破关注点分离的限制)。

MicroStream没有该限制。它可以正确处理任意对象图,而不会破坏它们的引用。
他写道,到目前为止,保持参照一致性不变并不是“尝试做太多事情”。这是“做得正确”。一个人只需要知道如何正确地做。如果正确完成,它甚至是微不足道的。
因此,根据Protobuf-Serialization的局限性(“恶魔般的脚步”),它可能几乎无法甚至根本无法与MicroStream相提并论。

当然,您始终可以针对自己的特定需求创建一些性能比较测试,并查看哪种技术最适合您。只需确保您了解某种技术对您施加的限制(破坏的参照一致性,禁止的类型,必需的注释,必需的默认构造函数/ getter / setter等)。
MicroStream没有任何*。

(*)原因:在技术上可能的情况下,有意排除序列化/存储系统内部(例如线程)或非实体(例如lambda或代理实例)的可能性。

Jackson:使用不同的属性名称序列化/反序列化 - java

我有这个POJO:public class SetPoint { private String tagName; //more fields //getters and setters } 我从REST API获取SetPoints,对它们进行处理,然后再次发送。问题是我想从JSON反序列化SetPoint,例如:{ "tagnameOpc…

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…