Unity 自动内存管理

来源:互联网 发布:说文解字通论 知乎 编辑:程序博客网 时间:2024/05/13 21:41


了解自动内存管理

当创建对象,字符串或数组(也即引用类型)时,它们会存储在堆(heap)上. 当它们不再被使用时,它们占用的内存可以被回收,并用作他用。如果不需要使用的内存始终被占用而不释放,就会造成内存泄露。以前,通常需要由程序员通过适当的函数调用来分配和回收内存. 现在,Unity的Mono engine会自动管理内存. 这就减少了程序员手动分配和回收内存的代码量,避免了内存泄露。

分配空间和垃圾收集

内存管理器跟踪堆中的已知的未使用的空闲空间。当请求分配新的内存块(比如实例化一个新的物体)时,内存管理器会从空闲空间中分配一个内存块并将该内存块从空闲空间表中移除。后续请求都会以同样方式进行处理,直到没有足够大的空闲来分配所需的块大小。此时,从堆中分配出去的所有内存中,(几乎)总是有些部分在此时不被使用了。对于堆内存上所存储的对象来说,只有存在能够指向它们的引用变量,它们才能被访问。 如果一个内存块的所有引用都不存在了(ie, 引用变量被重新赋值,或者引用变量是超出作用域的局部变量),那么它所占据的内存可以安全地进行重新分配。

为了确定哪些堆块不再被使用,内存管理器会搜索当前所有活动的引用变量,并把它们所引用的堆块标记为“live”。搜索完成时,活动堆块之间的空间被视为空闲空间,接下来可以分配给新的对象。定位(查找)和释放未使用内存的过程被称为garbage collection (或简称为GC).

GC的优化

GC对程序员来说是自动的,不可见的 ,但是GC过程中会占用大量CPU时间. 如果正确使用GC,自动内存管理在总体性能上等于或优于手动分配. 然而,程序员一定要避免引发超于常规次数的GC。

下面的算法

function ConcatExample(intArray: int[]) {var line = intArray[0].ToString();for (i = 1; i < intArray.Length; i++) {line += ", " + intArray[i].ToString();}return line;}
在这里,每一次循环时,line这个引用变量都会指向一个新的string对象,那么line之前所指向的对象就死掉了(因为没有一个引用变量指向它,我们将没有任何办法使用到它)


Requesting a Collection 请求回收As noted above, a garbage collection can sometimes create a pause in execution, especially if the search for live objects turns out to be complicated. If this happens during gameplay then the result is likely to be noticeable but there may be other occasions in the game where a pause would be harmless (eg, when the screen is faded out or a menu is being shown). It is possible to request that the system perform a garbage collection even when the heap isn't full, so as to avoid a pause at a more inopportune time. This is done with the System.GC.Collect function:- 如上所述,一个垃圾收集有时可以引发一个暂停执行,尤其是如果是对活动对象的搜索结果的话会更复杂。如果在游戏中发生这种情况,那么其结果很可能是明显的,但有可能在比赛中的其他场合,暂停将是无关紧要的(例如,当屏幕上消失或正在显示菜单)。尽可能要求系统执行垃圾回收以避免在不合时宜的时间中断执行,即使堆空间不是满的。可以通过System.GC.Collect功能完成: -  function NotVeryMuchHappeningInGame() {System.GC.Collect();  }Note that the memory manager doesn't necessarily perform a collection when this function is called. It is merely a suggestion that it would be a good time for GC if it is necessary. 注意在调用函数时内存管理并不一定执行回收。它只是建议你还是有必要在适当的时机使用GC。




如果频繁地进行GC,很明显会影响游戏的性能,尤其是当游戏中的物体正在移动时,我们会明显觉得卡顿,所以我们可以在物体不移动的时候,比如显示主界面的时候,主动请求GC,调用System.GC.Clollect()


使用对象池有时也可以减少GC的次数,在实例化物体并向对象池中添加时,我们也应该在主界面或卡顿对游戏影响不大的时候进行。




0 0