为什么这个内存管理技巧有效?
Why this memory management trick works?
参考 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;
诀窍是在程序启动时预先分配一些内存块。
为什么这个技巧有效?
这些块在预分配时对应用程序来说是某种 "registered"(或 "bound"),因此即使 tmp
在 Start()
完成后,OS 仍将这些块视为 "registered" 应用程序?
由于chunks是"registered"给应用程序的,所以应用程序的heap size扩大到一定大小,下次获取内存chunk时,OS直接从this的heap中取申请。
我的解释对吗?不管Yes or No,谁能详细解释一下,谢谢
Why does this trick work?
这个技巧之所以有效,是因为应用程序不会 return 内存到 OS,除非 OS 内存管理器不足并明确要求他们这样做,然后他们会尽可能地腾出时间。假设一旦分配了内存,就会再次需要它。如果它已经被分配,就没有理由 return 它回到 OS,除非它真的需要使用它。
这不是真正的把戏。这是 Unity3D 的某些部分处理内存的方式。
在 Unity3D 中,您有一些对象由 Mono 处理并将被垃圾收集,而一些对象由 Unity 处理,不会被垃圾收集。字符串、整数等会被 Mono 自动清理,我们不必为此担心。 Texture(2D) 等不是,我们必须手动处理这些对象。
当请求内存时,首先发生的事情是内存管理器从 OS 扫描应用程序当前分配的内存,寻找足够大的块来存储您请求的数据。如果找到匹配项,则使用该内存。如果未找到匹配项,则应用程序将从 OS 请求额外的内存以存储您的数据。当这些数据不再用完时,它就会被垃圾回收,但应用程序仍会保留该内存。本质上,它在内存上设置了一个标志,表明它是 'usable' 或可重新分配的。这通过从不 return 减少对 OS 的内存请求。
这意味着两件事;
1) 你的应用程序的内存只会不断增长,而不会return内存增加到OS。在移动设备上,这很危险,因为如果您使用太多内存,您的应用程序将被终止。
2) 您的应用程序实际上可能分配了比实际需要更多的内存。这是由于内存碎片。您的应用程序内存池中可能有 10MB 的可用内存,但这些块中没有一个大到足以容纳您需要存储的数据。因此,应用程序可能会从 OS 请求更多内存,因为没有一块可用的连续内存可用。
因为您正在创建一个大对象,因此需要内存,当您将该对象设置为 null 并向垃圾收集器发出应用程序不再需要内存的信号时,重新分配保留的内存会更快到其他对象,而不是从 OS 请求额外的内存。这就是为什么理论上这种特定方法速度很快并且会导致较少的性能峰值,因为垃圾收集器的调用频率较低。特别是因为这是一个大的、连续的内存分配。
参考 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;
诀窍是在程序启动时预先分配一些内存块。
为什么这个技巧有效?
这些块在预分配时对应用程序来说是某种 "registered"(或 "bound"),因此即使 tmp
在 Start()
完成后,OS 仍将这些块视为 "registered" 应用程序?
由于chunks是"registered"给应用程序的,所以应用程序的heap size扩大到一定大小,下次获取内存chunk时,OS直接从this的heap中取申请。
我的解释对吗?不管Yes or No,谁能详细解释一下,谢谢
Why does this trick work?
这个技巧之所以有效,是因为应用程序不会 return 内存到 OS,除非 OS 内存管理器不足并明确要求他们这样做,然后他们会尽可能地腾出时间。假设一旦分配了内存,就会再次需要它。如果它已经被分配,就没有理由 return 它回到 OS,除非它真的需要使用它。
这不是真正的把戏。这是 Unity3D 的某些部分处理内存的方式。
在 Unity3D 中,您有一些对象由 Mono 处理并将被垃圾收集,而一些对象由 Unity 处理,不会被垃圾收集。字符串、整数等会被 Mono 自动清理,我们不必为此担心。 Texture(2D) 等不是,我们必须手动处理这些对象。
当请求内存时,首先发生的事情是内存管理器从 OS 扫描应用程序当前分配的内存,寻找足够大的块来存储您请求的数据。如果找到匹配项,则使用该内存。如果未找到匹配项,则应用程序将从 OS 请求额外的内存以存储您的数据。当这些数据不再用完时,它就会被垃圾回收,但应用程序仍会保留该内存。本质上,它在内存上设置了一个标志,表明它是 'usable' 或可重新分配的。这通过从不 return 减少对 OS 的内存请求。
这意味着两件事;
1) 你的应用程序的内存只会不断增长,而不会return内存增加到OS。在移动设备上,这很危险,因为如果您使用太多内存,您的应用程序将被终止。
2) 您的应用程序实际上可能分配了比实际需要更多的内存。这是由于内存碎片。您的应用程序内存池中可能有 10MB 的可用内存,但这些块中没有一个大到足以容纳您需要存储的数据。因此,应用程序可能会从 OS 请求更多内存,因为没有一块可用的连续内存可用。
因为您正在创建一个大对象,因此需要内存,当您将该对象设置为 null 并向垃圾收集器发出应用程序不再需要内存的信号时,重新分配保留的内存会更快到其他对象,而不是从 OS 请求额外的内存。这就是为什么理论上这种特定方法速度很快并且会导致较少的性能峰值,因为垃圾收集器的调用频率较低。特别是因为这是一个大的、连续的内存分配。