c# – 为什么这个内存管理技巧可行?

this Unity documentation并转到部分

Large heap with slow but infrequent garbage collection

    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;

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

为什么这个招式有效?

这些块在预分配时是否为“注册”(或“绑定”),因此即使在完成Start()时tmp正在被释放,操作系统仍将这些块视为“注册“到应用程序?
由于块被“注册”到应用程序,所以应用程序的堆大小扩展到一定的大小,下次获取内存块时,操作系统只会从该应用程序堆中选择它.

我的解释是否正确?不管是或否,有人可以详细解释,谢谢.

最佳答案
这不是一个伎俩.这是Unity3D部分处理内存的方式.

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

当进行内存请求时,首先发生的情况是内存管理器从操作系统扫描应​​用程序当前分配的内存足够大以存储要请求的数据.如果找到匹配,则使用该内存.如果未找到匹配项,则应用程序将从操作系统请求其他内存以存储数据.当这个数据不再耗尽时,它被垃圾回收,但应用程序仍然保留该内存.实质上,它在内存上设置一个标志,表示它是“可用”或可重新分配的.这样可以减少对操作系统的内存请求.

这是什么意思是两件事情?

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

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

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

转载注明原文:c# – 为什么这个内存管理技巧可行? - 代码日志