C# GC.Collect()
用C#写了一个运用ICE组件进行接口通信的服务程序,程序运行很正常,可是在客户端调用ICE接口时出现了大量的数据丢失,而且偶尔还通信不上,服务端最明显的现象就是telnet服务的通信端口时不通(cmd窗口一闪而过),经过大量时间的跟踪测试,最终只能通过tfs上的历史修改记录来一步一步恢复还原,最后问题定位在GC.Collect();这一句代码上:大部份接口都存在这一句代码进行内存回收,而把这句注掉以后,通信和数据传输都正常下来了!
MSDN对于强制垃圾回收的解释:
垃圾回收 GC 类提供 GC.Collect 方法,您可以使用该方法让应用程序在一定程度上直接控制垃圾回收器。通常情况下,您应该避免调用任何回收方法,让垃圾回收器独立运行。在大多数情况下,垃圾回收器在确定执行回收的最佳时机方面更有优势。但是,在某些不常发生的情况下,强制回收可以提高应用程序的性能。当应用程序代码中某个确定的点上使用的内存量大量减少时,在这种情况下使用 GC.Collect 方法可能比较合适。例如,应用程序可能使用引用大量非托管资源的文档。当您的应用程序关闭该文档时,您完全知道已经不再需要文档曾使用的资源了。出于性能的原因,一次全部释放这些资源很有意义。有关更多信息,请参见 GC.Collect 方法。
在垃圾回收器执行回收之前,它会挂起当前正在执行的所有线程。如果不必要地多次调用 GC.Collect,这可能会造成性能问题。您还应该注意不要将调用 GC.Collect 的代码放置在程序中用户可以经常调用的点上。这可能会削弱垃圾回收器中优化引擎的作用,而垃圾回收器可以确定运行垃圾回收的最佳时间。
另外做一些扩展阅读:
首先我们要知道托管代码中的对象什么时候回收我们管不了(除非用GC.Collect强迫GC回收,这不推荐,后面会说明为什么)。GC会在它"高兴"的时候执行一次回收(这有许多原因,比如内存不够用时。这样做是为了提高内存分配、回收的效率)。那么如果我们用Destructor呢?同样不行,因为.NET中Destructor的概念已经不存在了,它变成了Finalizer,这会在后面讲到。目前请记住一个对象只有在没有任何引用的情况下才能够被回收。为了说明这一点请看下面这一段代码:[C#]
object objA = new object();
object objB = objA;
objA = null;
// 强迫回收。
GC.Collect();
objB.ToString();
[Visual Basic]
Dim objA As New Object()
Dim objB As Object = objA
objA = Nothing
' 强迫回收。
GC.Collect()objB.ToString()
这里objA引用的对象并没有被回收,因为这个对象还有另一个引用,ObjB。对象在没有任何引用后就有条件被回收了。当GC回收时,它会做以下几步:确定对象没有任何引用。检查对象是否在Finalizer表上有记录。如果在Finalizer表上有记录,那么将记录移到另外的一张表上,在这里我们叫它Finalizer2。如果不在Finalizer2表上有记录,那么释放内存。在Finalizer2表上的对象的Finalizer会在另外一个low priority的线程上执行后从表上删除。当对象被创建时GC会检查对象是否有Finalizer,如果有就会在Finalizer表中添加纪录。我们这里所说的记录其实就是指针。如果仔细看这几个步骤,我们就会发现有Finalizer的对象第一次不会被回收,也就是,有Finalizer的对象要一次以上的Collect操作才会被回收,这样就要慢一步,所以作者推荐除非是绝对需要不要创建Finalizer。为了证明GC确实这么工作而不是作者胡说,我们将在对象的复活一章中给出一个示例,眼见为实,耳听为虚嘛!^_^GC为了提高回收的效率使用了Generation的概念,原理是这样的,第一次回收之前创建的对象属于Generation 0,之后,每次回收时这个Generation的号码就会向后挪一,也就是说,第二次回收时原来的Generation 0变成了Generation 1,而在第一次回收后和第二次回收前创建的对象将属于Generation 0。GC会先试着在属于Generation 0的对象中回收,因为这些是最新的,所以最有可能会被回收,比如一些函数中的局部变量在退出函数时就没有引用了(可被回收)。如果在Generation 0中回收了足够的内存,那么GC就不会再接着回收了,如果回收的还不够,那么GC就试着在Generation 1中回收,如果还不够就在Generation 2中回收,以此类推。Generation也有个最大限制,根据Framework版本而定,可以用GC.MaxGeneration获得。在回收了内存之后GC会重新排整内存,让数据间没有空格,这样是因为CLR顺序分配内存,所以内存之间不能有空着的内存。现在我们知道每次回收时都会浪费一定的CPU时间,这就是我说的一般不要手动GC.Collect的原因(除非你也像我一样,写一些有关GC的示例!^_^)。
C# GC.Collect()的更多相关文章
- 关于GC.Collect在不同机器上表现不一致问题
2019.1.17,昨天项目更新后策划反应: 游戏卡,表现为:每走几步就卡一下.前天还没有. 但在我本机测试中,却没有任何卡顿感. QC同学的机器也卡.我去看了下,打开Profiler,没开deep, ...
- System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
System.GC.Collect();//垃圾回收,回收没有正常关闭的http连接
- 内存迟迟下不去,可能你就差一个GC.Collect
一:背景 1. 讲故事 我们有一家top级的淘品牌店铺,为了后续的加速计算,在程序启动的时候灌入她家的核心数据到内存中,灌入完成后内存高达100G,虽然云上的机器内存有256G,然被这么划掉一半看着还 ...
- 不得不知的CLR中的GC
引言 GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上.其实很多语言也有类似的东东, 如Java也有JIT 等等 GC基本概念 垃圾回收机制的算法有好多种 ...
- GC使用注意
GC.Collect() GC.WaitForPendingFinallizers() GC.KeepAlive 尽量不要new很大的Object 不要频繁的new生命周期很短的Object,这样会导 ...
- C#技术漫谈之垃圾回收机制(GC)
GC的前世与今生 虽然本文是以.NET作为目标来讲述GC,但是GC的概念并非才诞生不久.早在1958年,由鼎鼎大名的图林奖得主John McCarthy所实现的Lisp语言就已经提供了GC的功能,这是 ...
- 关于GC和析构函数的一个趣题
这个有趣的问题感谢装配脑袋友情提供. 请看如下代码: public class Dummy { public static Dummy Instance; ; ~Dummy() { Instance ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC
一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...
- 从C#垃圾回收(GC)机制中挖掘性能优化方案
GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...
随机推荐
- 九度OJ 1387 斐波那契数列
题目地址:http://ac.jobdu.com/problem.php?pid=1387 题目描述: 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.斐波那契数列的定义 ...
- hdu 4778 Gems Fight! 博弈+状态dp+搜索
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4102743.html 题目链接:hdu 4778 Gems Fight! 博弈+状态dp+搜 ...
- iOS网络编程总结
好长时间没有进行更行了,最近学到AFNetworking框架,在学习完成之后做出一个总结 1.第三方网络的框架 AFNEtworking使用简单,对最新的iOS特性都有很好的支持,对NSURL进行了封 ...
- centos 6.5 x64编译有python的vim7.4
wget ftp://ftp.vim.org/pub/vim/extra/vim-7.2-extra.tar.gzwget ftp://ftp.vim.org/pub/vim/extra/vim-7. ...
- 在Intellij IDEA或者PhpStorm下用X-debug调试PHP
用Intellij IDEA或者PhpStorm使用X-debug来调试PHP,主要需要配置的部分有三个地方,分别为php.ini的配置,IDEA的配置和浏览器的配置,主要如下,以备忘: php.in ...
- 021,lambda 表达式
021,lambda 表达式 匿名函数: 快速定义单行的最小函数,是从lisp借用来的,可以用在任何需要函数的地方 >>> def ds(x): return 2*x + ...
- c#让窗体永在最前 调用windows api 将窗体设为topmost
有时候应用程序需要将一个窗体始终位于屏幕的最前面,即使切换到其它窗体也能看到该窗体,这样的窗体就叫做TopMost窗体. 用C#制作TopMost窗体之前,首先要了解如何声明SetWindowPos函 ...
- boost linux 下安装
1. 在boost 官网 http://www.boost.org/doc/libs/ 下载最新的boost 安装包 2. 解压至 /usr/local/ 目录下 3. cd /usr/local/b ...
- 如何实现一个malloc函数
一.概述 1.malloc简介 函数所在头文件:<stdlib.h> 函数原型是:void *malloc (size_t n) 函数功能:在内存的动态存储区中分配一个长度为size的连续 ...
- spring IOC源码分析(3)
1.IOC容器的依赖注入 Spring中,依赖注入是在用户第一次向IOC容器索要Bean时触发的(通过getBean方法). 在BeanFactory中我们看到getBean(String…)函数,它 ...