MicroStream(反)序列化是如何工作的?
How does MicroStream (de)serialization work?
我想知道 MicroStream 的序列化是如何详细工作的。
由于它被描述为 "Super-Fast" 它必须依赖代码生成,对吗?还是基于反射?
与 Protobuf 序列化相比,它的表现如何,Protobuf 序列化依赖于直接读出 java 字段并将它们写入字节缓冲区的代码生成,反之亦然。
在大规模序列化对象时使用反射会大大降低性能,不是吗?
我正在寻找一种快速的方法来为多人游戏传输和保存对象,并且每一毫秒都很重要。 :)
提前致谢!
PS: 由于我没有足够的声望,我无法创建 "microstream"-标签。 https://microstream.one/
我是 MicroStream 的首席开发人员。
(这不是别名帐户。我真的刚刚创建了它。我在 Whosebug 上阅读了 10 年左右,但从来没有理由创建帐户。直到现在。)
在每次初始化时,MicroStream 都会分析所有必需实体和值类型 classes 的当前运行时版本,并从中导出优化的元数据。
在运行时遇到到目前为止未知的 class 时,也会执行相同的操作。
每次反射都会进行分析,但由于每次处理 class 只分析一次,因此反射性能成本可以忽略不计。
实际的存储和加载或序列化和反序列化是通过基于创建的元数据优化的框架代码完成的。
如果 class 布局发生变化,类型分析会创建一个映射,从存储 class' 实例的字段布局到当前 class 的字段布局。
如果可能(明确的更改或通过一些可配置的启发式方法)自动进行,否则通过用户提供的映射进行。性能保持不变,因为 JVM 不关心它(简单地说)是否将加载的值 #3 复制到位置 #3 或位置 #5。都在元数据中。
使用了 ByteBuffers,更准确地说是直接 ByteBuffers,但仅作为堆外内存的锚点,可通过直接 "Unsafe" 低级操作进行处理。如果您不熟悉 "Unsafe" 操作,一个简短的概念是:"It's as direct and fast as C++ code."。您可以非常快速且接近记忆地做任何您想做的事情,但您也要对所有事情负责。更多详情,google "sun.misc.Unsafe".
没有生成代码。不使用字节码破解、通过代理或类似的猴子业务默认替换实例。在技术层面上,它只是一个 Java 库(包括 "Unsafe" 用法),但是有很多正确设计的逻辑。
附带说明:反射并不像通常认为的那样慢。不再。是的,但在过去的 Java 版本中已经进行了相当多的优化。
如果每个操作都必须重新执行所有 class 分析、字段查找等(很多框架似乎都这样做,因为它们写得不好),这只会很慢。如果将字段收集(设置可访问性等)一次然后缓存,反射实际上快得惊人。
关于与 Protobuf-Serialization 的比较:
我不能说任何关于它的具体信息,因为我没有使用过 Protocol Buffers 并且我不知道它在内部是如何工作的。
与复杂技术一样,可能很难进行真正有意义的比较,因为不同的技术具有不同的优化优先级和限制。
大多数序列化方法放弃了引用一致性,但只存储 "data"(即,如果两个对象引用第三个对象,反序列化将创建第三个对象的两个实例。
像这样:A->C<-B ==序列化==> A->C1 B->C2。
这基本上 breaks/ruins/destroys 对象图并使循环图的序列化变得不可能,因为它创建并无休止地级联复制。例如,参见 JSON 序列化。有趣的事。)
甚至 Brian Goetz 的 Java "Serialization 2.0" 草案也包含该限制(参见 "Limitations" at http://cr.openjdk.java.net/~briangoetz/amber/serialization.html)(以及另一个打破关注点分离的限制)。
MicroStream 没有这个限制。它可以正确处理任意对象图而不会破坏它们的引用。
正如他所写的那样,到目前为止,保持引用一致性完好无损 "trying to do too much"。是"doing it properly"。一个人只需要知道如何正确地做它。如果做得正确,它甚至是微不足道的。
因此,根据 Protobuf-Serialization 有多少限制 ("pacts with the devil"),它可能很难甚至根本无法与一般的 MicroStream 相提并论。
当然,您始终可以根据自己的特定要求创建一些性能比较测试,看看哪种技术最适合您。只要确保您了解某种技术强加给您的限制(破坏的引用一致性、禁止的类型、必需的注释、必需的默认构造函数/getters/setters 等)。
MicroStream 有 none*.
(*) 在合理范围内:Serializing/storing 系统内部(例如 Thread)或非实体(例如 lambda 或代理实例)在技术上可能被有意排除。
我想知道 MicroStream 的序列化是如何详细工作的。
由于它被描述为 "Super-Fast" 它必须依赖代码生成,对吗?还是基于反射?
与 Protobuf 序列化相比,它的表现如何,Protobuf 序列化依赖于直接读出 java 字段并将它们写入字节缓冲区的代码生成,反之亦然。
在大规模序列化对象时使用反射会大大降低性能,不是吗?
我正在寻找一种快速的方法来为多人游戏传输和保存对象,并且每一毫秒都很重要。 :)
提前致谢!
PS: 由于我没有足够的声望,我无法创建 "microstream"-标签。 https://microstream.one/
我是 MicroStream 的首席开发人员。 (这不是别名帐户。我真的刚刚创建了它。我在 Whosebug 上阅读了 10 年左右,但从来没有理由创建帐户。直到现在。)
在每次初始化时,MicroStream 都会分析所有必需实体和值类型 classes 的当前运行时版本,并从中导出优化的元数据。 在运行时遇到到目前为止未知的 class 时,也会执行相同的操作。 每次反射都会进行分析,但由于每次处理 class 只分析一次,因此反射性能成本可以忽略不计。 实际的存储和加载或序列化和反序列化是通过基于创建的元数据优化的框架代码完成的。
如果 class 布局发生变化,类型分析会创建一个映射,从存储 class' 实例的字段布局到当前 class 的字段布局。 如果可能(明确的更改或通过一些可配置的启发式方法)自动进行,否则通过用户提供的映射进行。性能保持不变,因为 JVM 不关心它(简单地说)是否将加载的值 #3 复制到位置 #3 或位置 #5。都在元数据中。
使用了 ByteBuffers,更准确地说是直接 ByteBuffers,但仅作为堆外内存的锚点,可通过直接 "Unsafe" 低级操作进行处理。如果您不熟悉 "Unsafe" 操作,一个简短的概念是:"It's as direct and fast as C++ code."。您可以非常快速且接近记忆地做任何您想做的事情,但您也要对所有事情负责。更多详情,google "sun.misc.Unsafe".
没有生成代码。不使用字节码破解、通过代理或类似的猴子业务默认替换实例。在技术层面上,它只是一个 Java 库(包括 "Unsafe" 用法),但是有很多正确设计的逻辑。
附带说明:反射并不像通常认为的那样慢。不再。是的,但在过去的 Java 版本中已经进行了相当多的优化。 如果每个操作都必须重新执行所有 class 分析、字段查找等(很多框架似乎都这样做,因为它们写得不好),这只会很慢。如果将字段收集(设置可访问性等)一次然后缓存,反射实际上快得惊人。
关于与 Protobuf-Serialization 的比较:
我不能说任何关于它的具体信息,因为我没有使用过 Protocol Buffers 并且我不知道它在内部是如何工作的。 与复杂技术一样,可能很难进行真正有意义的比较,因为不同的技术具有不同的优化优先级和限制。
大多数序列化方法放弃了引用一致性,但只存储 "data"(即,如果两个对象引用第三个对象,反序列化将创建第三个对象的两个实例。 像这样:A->C<-B ==序列化==> A->C1 B->C2。 这基本上 breaks/ruins/destroys 对象图并使循环图的序列化变得不可能,因为它创建并无休止地级联复制。例如,参见 JSON 序列化。有趣的事。) 甚至 Brian Goetz 的 Java "Serialization 2.0" 草案也包含该限制(参见 "Limitations" at http://cr.openjdk.java.net/~briangoetz/amber/serialization.html)(以及另一个打破关注点分离的限制)。
MicroStream 没有这个限制。它可以正确处理任意对象图而不会破坏它们的引用。 正如他所写的那样,到目前为止,保持引用一致性完好无损 "trying to do too much"。是"doing it properly"。一个人只需要知道如何正确地做它。如果做得正确,它甚至是微不足道的。 因此,根据 Protobuf-Serialization 有多少限制 ("pacts with the devil"),它可能很难甚至根本无法与一般的 MicroStream 相提并论。
当然,您始终可以根据自己的特定要求创建一些性能比较测试,看看哪种技术最适合您。只要确保您了解某种技术强加给您的限制(破坏的引用一致性、禁止的类型、必需的注释、必需的默认构造函数/getters/setters 等)。 MicroStream 有 none*.
(*) 在合理范围内:Serializing/storing 系统内部(例如 Thread)或非实体(例如 lambda 或代理实例)在技术上可能被有意排除。