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

Leo*_*ert 2 java serialization deserialization microstream

我想知道 MicroStream 的序列化是如何详细工作的。既然它被描述为“超快”,它必须依赖于代码生成,对吗?还是基于反射?
与 Protobuf-Serialization 相比,它的性能如何,Protobuf-Serialization 依赖于直接读取 java 字段并将它们写入字节缓冲区的代码生成,反之亦然。
在大规模序列化​​对象时,使用反射会大大降低性能,不是吗?

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

提前致谢!

PS:由于我没有足够的声望,我无法创建“微流”标签。https://microstream.one/

MST*_*STM 10

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

在每次初始化时,MicroStream 都会分析所有必需实体和值类型类的当前运行时版本,并从中导出优化的元数据。在运行时遇到迄今为止未知的类时也会这样做。每次反射都会进行分析,但由于对每个处理的类只进行一次,因此反射性能成本可以忽略不计。实际的存储和加载或序列化和反序列化是通过基于创建的元数据优化的框架代码完成的。

如果类布局发生变化,类型分析会创建从类实例存储在的字段布局到当前类的布局的映射。如果可能,自动(明确更改或通过一些可配置的启发式),否则通过用户提供的映射。性能保持不变,因为 JVM 不关心它(简单地说)是否将加载的值 #3 复制到位置 #3 或位置 #5。这一切都在元数据中。

使用 ByteBuffers,更准确地说是直接 ByteBuffers,但仅作为堆外内存的锚点,通过直接的“不安全”低级操作进行处理。如果您不熟悉“不安全”操作,一个简短而简单的概念是:“它和 C++ 代码一样直接和快速。”。您可以非常快速且接近记忆地做任何您想做的事情,但您也需要对所有事情负责。有关更多详细信息,请谷歌“sun.misc.Unsafe”。

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

附带说明:反射并不像通常认为的那么慢。不再。是的,但它在过去的一些 Java 版本中已经被优化了很多(s?)。如果每个操作都必须重新进行所有的类分析、字段查找等,那么它只会很慢(很多框架似乎都这样做,因为它们只是写得不好)。如果字段被收集(设置为可访问等)一次然后缓存,反射实际上是惊人的快。

关于与 Protobuf-Serialization 的比较:

我不能说任何关于它的具体内容,因为我没有使用过 Protocol Buffers,我不知道它在内部是如何工作的。对于复杂的技术,通常很难进行真正有意义的比较,因为不同的技术具有不同的优化优先级和限制。

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

MicroStream 没有这个限制。它可以正确处理任意对象图而不会破坏它们的引用。正如他所写的那样,保持参照一致性的完整性远不是“试图做太多事情”。它是“正确地做”。一个人只需要知道如何正确地做到这一点。如果做得正确,它甚至是相当微不足道的。因此,取决于 Protobuf-Serialization 有多少限制(“与魔鬼的契约”),它可能很难甚至根本无法与 MicroStream 相提并论。

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

(*) 在合理范围内:序列化/存储系统内部(例如线程)或非实体(例如 lambda 或代理实例)虽然在技术上可行,但有意排除在外。

  • 非常感谢您非常详细的回答,这听起来棒极了!特别是在反序列化过程中将对象引用组合在一起听起来很神奇。我会做一些原型设计,看看它是否适合我的游戏。我认为棘手的是,我不仅需要存储它们,还需要在客户端和服务器之间发送序列化的对象,而不是空中,并且客户端需要再次反序列化它们。 (2认同)