使用字节数组映射改进性能

可将映射中的值存储为字节数组而不是 POJO 格式,这会减少大型对象图可消耗的内存占用量。

好处

内存消耗量随对象图中的对象数增加而增加。通过将复杂对象图缩减为字节数组,只会在堆中保留一个对象而不是若干对象。随着堆中的对象数减少,Java™ 运行时要在垃圾回收期间搜索的对象数也会减少。

WebSphere® eXtreme Scale 使用的缺省复制机制为序列化,此操作的成本很高。例如,如果使用缺省复制方式 COPY_ON_READ_AND_COMMIT,那么读取时和获取时都会进行复制。在读取时,值通过使用字节数组扩充字节而不是创建副本,在落实时,值序列化至字节而不是创建副本。使用字节数组会产生与缺省设置等价的数据一致性,并且减少了内存使用量。

使用字节数组时,请注意优化序列化机制对实现内存消耗量减少很关键。要了解更多信息,请参阅调整序列化性能

配置字节数组映射

可通过将映射使用的 CopyMode 属性修改为设置 COPY_TO_BYTES 以使用 ObjectGrid XML 文件启用字节数组映射,如以下示例中所示:

<backingMap name="byteMap" copyMode="COPY_TO_BYTES" />

注意事项

必须考虑是否在给定场景中使用字节数组映射。尽管可减少内存使用量,但使用字节数组时处理器使用量会增加。

以下列表概述选择使用字节数组映射功能之前应考虑的几个因素。

对象类型

相比之下,对某些对象类型使用字节数组映射时,可能无法减少内存使用量。因此,不应对某些类型的对象使用字节数组映射。如果正将任何 Java 基本包装器用作值或未包含其他对象的引用的 POJO(仅存储基本字段),那么 Java 对象数已达到可能的最低值 - 只有一个。因为该对象使用的内存量已优化,所以不建议对这些类型的对象使用字节数组映射。字节数组映射更适用于所包含的其他对象或对象集合中的 POJO 对象总数大于 1 的对象类型。

例如,如果您的 Customer 对象具有公司地址和家庭地址,并且具有一组订单,那么可使用字节数组映射来减少堆中的对象数及这些对象使用的字节数。

本地访问

如果使用其他复制方式,那么创建副本时(如果可使用缺省 ObjectTransformer 克隆对象)或随已优化 copyValue 方法提供定制 ObjectTransformer 时可优化应用程序。与其他复制方式相比,在读取、写入或落实操作时复制会导致在本地访问对象时产生附加成本。例如,如果分布式拓扑中有近高速缓存或您正在直接访问本地或服务器 ObjectGrid 实例,那么使用字节数组映射时会因为序列化成本而导致访问和落实时间延长。如果使用数据网格代理程序或在使用 ObjectGridEventGroup.ShardEvents 插件时访问服务器主项,那么您会在分布式拓扑中见到类似成本。

插件交互

对于字节数组映射,客户机与服务器通信时不会扩充对象,除非服务器需要 POJO 格式。与映射值交互的插件将体验到性能下降,因为需要扩充值。

使用 LogElement.getCacheEntry 或 LogElement.getCurrentValue 的任何插件将见到此额外成本。如果要获取键,那么可使用 LogElement.getKey,这可以避免与 LogElement.getCacheEntry().getKey 方法相关联的额外开销。以下各节从使用字节数组的角度讨论插件。

索引和查询

要避免序列化开销,请使用字节数组,而不是 Java 对象。由于垃圾回收期间,JDK 要搜索的对象更少,因此在内存中存储时使用字节数组开销会低很多,且仅在需要时扩充这些数组。以前您仅在不需要使用查询或索引访问对象时使用字节数组,因为数据存储为字节并且只能通过键进行访问。但是,从 V7.1.1 开始,使用索引和查询的可行性增强,因为序列化程序插件提高了以前存在的 copy-to-bytes 限制。

[Version 8.6 and later]在 V8.6 中,当您使用 eXtremeIO (XIO) 时,您可以访问 eXtreme 数据格式 (XDF),这是缺省内置序列化程序。使用 XDF 以在数据网格中通过独立于语言的格式序列化和存储键和值。有关 XDF 的更多信息,请参阅将数据网格配置为使用 eXtreme 数据格式 (XDF)

乐观锁定

如果使用乐观锁定策略,那么执行更新和失效操作时会产生额外成本。这是因为必须在服务器上扩充值以获取版本值来执行乐观冲突检查。如果仅使用乐观锁定来保证访存操作,而不需要乐观冲突检查,那么您可以使用 com.ibm.websphere.objectgrid.plugins.builtins.NoVersioningOptimisticCallback 来禁用版本检查。

装入器

对于装入器,也会在 eXtreme Scale 运行时中因为装入器使用值时扩充和重新序列化该值而产生成本。仍可将字节数组映射与装入器配合使用,但应考虑在这类场景中更改该值带来的成本。例如,可在读取次数极多的高速缓存的上下文中使用字节数组功能。在此情况下,堆中对象较少并且内存用量较少带来的好处高于对插入和更新操作使用字节数组带来的成本。

ObjectGridEventListener

如果在 ObjectGridEventListener 插件中使用 transactionEnd 方法,那么访问 LogElement 的 CacheEntry 或当前值时会在服务器端因为远程请求而产生额外成本。如果该方法的实现不访问这些字段,那么不会产生额外成本。