代码改变世界

.net垃圾回收学习[NET 2.0 Performance Guidelines - Garbage Collection][翻译加学习]【2】

2011-08-28 16:13  一一九九  阅读(146)  评论(0编辑  收藏  举报

From:http://www.guidanceshare.com/wiki/.NET_2.0_Performance_Guidelines_-_Garbage_Collection

Set Unneeded Member variables to null before making long-running calls

在开始一段运行时间较长的代码之前,你应该明确的设置不需要的对象变量为NULL,以便在运行时间较长的代码调用之前能够被收集。如下代码所示:

class MyClass{
  private string str1;
  private string str2;
 
 void DoSomeProcessing(…){
   str1= GetResult(…);
   str2= GetOtherResult(…);
 }
 void MakeDBCall(…){
   PrepareForDBCall(str1,str2);
   str1=null;
   str2=null;
   // Make a database (long running) call
 }
}

这条建议适用于任何在静态上或者词法上可以到达但是实际上不需要的对象。

  • 加入你不再需要一个静态变量或者其他的Class,将其设置为NULL(注:这句话可能有问题,应该是任何的类变量而不是静态变量,静态变量释放到Type Handler中的,是不能够释放的)
  • If you can "prune" your state, that is also a good idea. You might be able to eliminate most of a tree before a long-running call, for instance.
  • 假如有任何能够在Long-running调用之前释放的Object,设置为NULL。

不要设置局部变量为NULL,因为JIT编译器会静态的决定局部变量的生命范围,所有没有必要明确的将其设置为NULL。代码示例如下:

void func(…)
{
  String str1;
  str1="abc";
  // Avoid this
  str1=null;
}

Minmize hidden allocations


由于只需要将内存指针移动到需要的位置,内存的分配是一个十分迅速的过程。然而,在某一个时间需要进行的内存垃圾回收却比较损害性能。所以注意表面上的几行代码实际上会导致很多的内存分配。比如说。String.Split使用一个Delimiter从一个原子符串中创建一个字符数组。为了这样做,String.Split为每一个分离出来的字符床都创建一个新的String对象,因此,在输入较大的环境下(比如说Sorting routine)中,使用String.split是代价较高的。

string attendees = "bob,jane,fred,kelly,jim,ann";
// In the following single line the code allocates 6 substrings, 
// outputs the attendees array, and the input separators array
string[] names = attendees.Split( new char[] {','});

也需要注意在一个循环中采用+=进行的字符串连接操作,最后,Hash方法和Compare方法中是不适合进行比较操作的,因为他们经常被重复的调用和查找和排序。For more information about how to handle strings efficiently, see "String Operations" later in this chapter.

Avoid or minimize Complex Object Graphs


避免使用包含大量应用其他对象的复杂的数据结构或者对象,这会给GC带来额外的工作,分配性能也会受到影响。简单的对象图很容易维护。一个常见的错误是将Gragh弄得太全面了。

References

Avoid Preallocating and Chunking Memory


C++ programmers often allocate a large block of memory (using malloc) and then use chunks at a time, to save multiple calls to malloc. This is not advisable for managed code for several reasons:

  • Allocation of managed memory is a quick operation and the garbage collector has been optimized for extremely fast allocations. The main reason for preallocating memory in unmanaged code is to speed up the allocation process. This is not an issue for managed code.
  • If you preallocate memory, you cause more allocations than needed; this can trigger unnecessary garbage collections.
  • The garbage collector is unable to reclaim the memory that you manually recycle.
  • Preallocated memory ages and costs more to recycle when it is ultimately released.