首页 文章

为什么这种内存管理技巧有效?

提问于
浏览
10

请参阅this Unity documentation并转到部分

大堆,缓慢但不常见的垃圾收集

var tmp = new System.Object[1024];

    // make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks
    for (int i = 0; i < 1024; i++)
        tmp[i] = new byte[1024];

    // release reference
    tmp = null;

诀窍是在程序启动时预先分配一些内存块 .

为什么这个技巧有效?

当预分配时,块是否为应用程序的某些部分_1172001_(或"bound"),因此即使在 Start() 完成时 tmp 被释放,操作系统仍将这些块视为应用程序的"registered"?由于块是应用程序的"registered",因此应用程序的堆大小扩展到一定大小,并且下次获取内存块时,操作系统只会从此应用程序的堆中选择它 .

我的解释是否正确?无论是或否,有人可以请详细解释,谢谢 .

2 回答

  • 4

    这不是一个诡计 . 这是Unity3D部分处理内存的方式 .

    在Unity3D中,您拥有由Mono处理并将被垃圾收集的对象,以及由Unity处理的对象,这些对象不会被垃圾回收 . 字符串,整数等由Mono自动清理,我们不必担心这一点 . 纹理(2D)等不是,我们必须手动处理这些对象 .

    当发出内存请求时,首先发生的事情是内存管理器从操作系统扫描应用程序当前分配的内存,以获得足以存储您请求的数据的块 . 如果找到匹配项,则使用该内存 . 如果未找到匹配项,则应用程序将从OS请求额外的内存以存储您的数据 . 当这些数据不再用完时,它会被垃圾收集,但应用程序仍保留该内存 . 本质上,它在内存上设置一个标志,表示它是“可用的”或可重新分配的 . 这样可以通过永不返回对OS的内存请求来减少 .

    这意味着两件事;

    1)您的应用程序的内存将继续增长,并且不会将内存返回到操作系统 . 在移动设备上,这很危险,就好像您使用太多内存一样,您的应用程序将被终止 .

    2)您的应用程序实际上可能会分配比实际需要更多的内存 . 这是由于内存碎片造成的 . 应用程序的内存池中可能有10MB的可用内存,但这些内存中的非内存大到足以容纳您需要存储的数据 . 因此,应用程序可能会从OS请求更多内存,因为没有可用的单个连续内存 .

    因为您正在创建一个大对象,因此请求内存,当您将该对象设置为null并向垃圾收集器发出应用程序不再需要内存的信号时,将内存重新分配给其他对象而不是从OS请求额外的内存 . 这就是为什么理论上这个特定的方法很快并且会导致较少的性能峰值,因为垃圾收集器的调用次数较少 . 特别是因为这是一个大的,连续的内存分配 .

  • 5

    为什么这个技巧有效?

    这个技巧有效,因为应用程序不会将内存返回给操作系统,除非操作系统内存管理器很低并明确要求它们这样做,然后它们将尽可能地释放 . 假设一旦分配了内存,就会再次需要它 . 如果已经分配,则没有理由将其返回给操作系统,除非确实需要使用它 .

相关问题