有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

内存Java分配:从预先存在/分配的池中分配对象

在Java程序中,当需要分配数千个类似大小的对象时,最好(在我看来)有一个带有保留项的“池”(这是一个单独的分配),这些保留项可以在需要时从中提取。这一个较大的分配不会像数千个较小的分配那样分割堆

显然,没有一种方法专门将对象引用指向内存中的地址(用于其成员字段)来设置池。即使新对象引用了池中的某个区域,仍然需要分配对象本身。如果不使用本机OS库,您将如何处理许多这样的分配


共 (4) 个答案

  1. # 1 楼答案

    如果您正在构建一个应用程序,其中可预测的响应时间非常重要,那么对象池(无论对象有多小)将为您带来好处。同样,池也是您试图池化的数据集有多大以及您的机器有多少物理内存的一个因素

    有大量的proof on the web表明对象池,无论对象有多小,都有利于应用程序性能

    您可以使用两种级别的池:

    • 基本对象(如向量)的池,每次必须使用向量形成地图或类似对象时,都会从池中检索这些对象
    • 将最常用的高级复合对象池化

    这通常是一个应用程序设计决策

    此外,在多线程应用程序中,您希望对分配和返回池的不同线程数量保持敏感。您当然不希望您的应用程序因争用而陷入困境,尤其是当您同时处理数千个对象时

  2. # 2 楼答案

    您可以尝试使用Commons Pool

    也就是说,除非我有证据证明JVM没有做我需要的事情,否则我可能会推迟优化对象创建

  3. # 3 楼答案

    @Dave和Casey,你不需要任何证据来证明连续内存布局可以提高缓存效率,这是大多数OOP应用程序的主要瓶颈,这些应用程序需要高性能,但遵循“过于理想化”的OOP设计轨迹

    人们通常认为GC是导致高性能Java应用程序性能低下的罪魁祸首,在修复它之后,只需保持这种状态,而不实际分析应用程序的内存行为。但是请注意,未缓存的内存指令本质上比算术指令更昂贵(并且由于内存访问<;->;计算缺口而变得越来越昂贵)。因此,如果您关心性能,您当然应该关心内存管理

    缓存感知(Cache-aware)或更一般的面向数据的编程是在多种应用程序中实现高性能的关键,如游戏或移动应用程序(以降低功耗)

    Here是DOP上的SO线程

    Here是索尼R&;D显示DOP应用于playstation游戏的有用性的部门(需要高性能)

    那么,如何解决Java通常不允许分配一块内存的问题呢?我的猜测是,当程序刚刚启动时,您可以假设已经分配的页面中几乎没有内部碎片。如果您现在有一个分配数千或数百万对象的循环,那么它们可能都是尽可能连续的。请注意,您只需要确保连续对象延伸到同一缓存线上,而在许多现代系统中,缓存线只有64字节。另外,如果您真的关心应用程序的(内存)性能,请查看DOP幻灯片

    简而言之:总是一次分配多个对象(增加分配的时间局部性),并且,如果您的GC有碎片整理,请事先运行它,否则请尝试将此类分配减少到程序的开始

    我希望这对你有帮助, -多米

    PS:@Dave,公用池库不会连续分配对象。它只通过将分配放入引用数组、嵌入到堆栈、链表或类似文件中来跟踪分配

  4. # 4 楼答案

    别担心。除非您已经对正在运行的实际代码进行了大量的测试和分析,并且知道这是垃圾收集的一个问题,并且JVM的工作做得不够好,否则请将您的时间花在其他地方