关于.NET内存中的堆和栈
今天中午李建忠老师发了一条关于class性能好还是struct性能好(换言之、堆性能好?还是栈性能好?)的话题微博,引发包括老赵这些牛人级的开发人员的热烈讨论。作为.NET开发背景的人,一般都会认为struct的性能会比class更好些,因为在应用程序的内存中,struct是保持在堆栈上,而class是保存在托管堆上,而栈的性能比堆的性能要高,为什么呢,我是基于下面几点的考虑(注:这里讨论的是.NET应用程序内存中的堆和栈,不是数据结构中的堆和栈):
1).NET中栈的空间是内存自维护的,即用完即清除;
2).NET中堆的空间的需要垃圾回收器回收释放。而垃圾回收器启动回收工作的时候,会暂停你程序的所有线程,然后根据一定的算法找出没有不再在程序中使用的对象并删除它们。然后GC会重新组织堆中所有剩下的对象来节省空间,并调整栈和堆中所有与这些对象相关的指针。这个过程是很耗费性能的,显然会比内存自动管理栈中的值类型的空间费劲的多。
如果你了解了上面这些,也许你想当然地认为stack会比class具有更好的使用性能,但是牛人的厉害之处就是不会想当然那么考虑问题,他们考虑问题的深度和广度都会比我们这些一般的开发人员要宽广深邃的多。所以老赵提问"struct传递的时候是拷贝完整对象的,class是引用,那么看上去拷贝引用代价更低啊,为什么说s性能高?"?
另外还有一个重要的问题是,值类型不一定就一定会保存在堆栈上的,值类型和指针总是放在它们被声明的地方。关于这点的详解,可以点击文章阅读。
我们在面向对象设计时,在遇到是struct还是class这样的疑问时,除了考虑上面所说的性能外,我觉得还要考虑你设计对象抽象的层次。对于逻辑复杂,抽象性比较高的对象设计为类合理些(结构不支持继承这些特性的)。对于只是存储值而且不会大量复制的对象设计成结构合理些。
对于是应该使用struct还是class,听听李建忠老师最后对他抛出的一个问题的总结吧:讨论class性能好,还是struct性能好,就像讨论“生孩子主要是man的功劳,还是woman的功劳“一样。简单说:长生存周期的放在heap好(好几个栈易做图享访问,全局持有),短生存周期的放在stack好(只在自己栈中用,不拷贝,不传递,不保存到集合中)。所以是heap+stack性能最好。
如果您对这个问题有更好的理解和认识,请留言讨论,以帮助更多想深入理解堆栈和堆的区别以写出更高质量代码的程序员。
后记:看到老赵的留言,我内心诚惶诚恐,恐曲解了大牛意思误导别人,今天老赵发了很多条微博来讨论这个问题,可以访问老赵的微博,关于class和struct孰优孰劣这个问题,老赵目前的观点是“这题的结论就是──基本没结论”,但我们程序设计的时候,必须在class和struct中选其一而用之,所以,诸位看官,权衡一番,到底选谁,自己决定吧。
补充:Web开发 , ASP.Net ,