引用这个统一文档并转到
具有缓慢但不频繁的垃圾收集的大型堆
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;诀窍是在程序开始时预先分配一些内存块。
为什么这个把戏起作用了?
在预先分配应用程序时,这些块是否是某种类型的“注册”(或“绑定”),因此即使tmp在Start()完成时被释放,操作系统仍然将这些块视为“注册”到应用程序?由于块是“注册”到应用程序的,所以应用程序的堆大小被扩展到一定的大小,下次它获得内存块时,OS只会从这个应用程序的堆中选择它。
我的解释正确吗?无论是或否,有谁能详细解释一下,谢谢。
发布于 2015-05-19 13:04:20
这不是真正的诡计。这是Unity3D部分处理内存的方式。
在Unity3D中,您有由Mono处理的对象,这些对象将被垃圾收集,而那些由Unity处理的对象将不会被垃圾收集。字符串、ints等是由Mono自动清理的,我们不必担心这一点。纹理(2D)s等不是,我们必须手动处理这些对象。
当请求内存时,首先发生的事情是内存管理器从操作系统中扫描应用程序当前分配的内存,找出足够大的块来存储所请求的数据。如果找到匹配,则使用该内存。如果找不到匹配,则应用程序将从操作系统请求额外的内存,以便存储数据。当这些数据不再被耗尽时,就会被垃圾收集,但是应用程序仍然保留着这个内存。本质上,它在内存中设置了一个标志,表示它是“可用的”或可重新分配的。这减少了对操作系统的内存请求,因为它从不返回。
这意味着两件事;
1)应用程序的内存只会继续增长,不会将内存返回到操作系统。在移动设备上,这是危险的,因为如果您使用过多的内存,您的应用程序将被终止。
2)您的应用程序实际分配的内存可能比实际需要的要多。这是由于内存支离破碎。您可能在应用程序的内存池中有10 in的可用内存,但是这些块中没有一个足够大来存储您需要存储的数据。因此,应用程序可能会从操作系统请求更多的内存,因为没有一个可以使用的连续内存。
因为您正在创建一个大型对象,因此请求内存,因此,当您将该对象设置为null并向垃圾收集器发送应用程序不再需要内存的信号时,将保留内存重新分配给其他对象比从操作系统请求额外内存要快一些。这就是为什么从理论上讲,这个特定的方法是快速的,并且随着垃圾收集器调用频率的降低,性能峰值会降低。特别是这是一个大型的、连续的内存分配。
发布于 2015-05-19 10:50:30
为什么这个把戏起作用了?
这个技巧之所以奏效,是因为应用程序不会将内存返回到OS,除非OS内存管理器很低,并明确要求它们这样做,这样它们就会尽可能地释放内存。有一种假设,即一旦分配了内存,就会再次需要内存。如果已经分配了它,则没有理由将其返回到操作系统,除非它确实需要使用它。
https://stackoverflow.com/questions/30323411
复制相似问题