C#WebAPI垃圾收集

Ale*_*der 1 c# garbage-collection memory-leaks asp.net-web-api

我刚刚将第一个C#WebAPI应用程序交付给第一个客户.在正常负载下,性能最初甚至比我预期的要好.原来.

一切都工作正常,直到某些时候,内存已经启动,垃圾收集开始乱成一团(如"它收集的物品还没有垃圾").那时,有多个W3WP线程,总共有10个ram,每个工人有一个单位数的演出.重新启动IIS后,一切都恢复正常,但当然内存使用率再次上升.

如果我错了,请纠正我,但是

  • C#不应该有自动垃圾回收吗?
  • GC收集WebAPI应用程序的垃圾应该不容易吗?

请帮助我:

  • 如何明确说明GC应该收集什么,从而防止内存泄漏?是someBigList = null;要走的路?
  • 如何检测内存泄漏的位置?

编辑:让我澄清一些事情.

我的.NET WebAPI应用程序主要是一堆

public class MyApiController:ApiController
{
    [HttpGet]
    public MyObjectClass[] MyApi(string someParam) {
        List<MyObjectClass> list = new List<MyObjectClass>();
        ...
        for/while/foreach {
            MyObjectClass obj = new MyObjectClass();
            obj.firstStringAttribute = xyz;
            ...
            list.Add(obj);
        }
        return list.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,GC应该很简单:在"返回"之后,所有局部变量都应该是垃圾.然而,每次调用时,使用的内存都会增加.

我最初认为C#WebAPI程序的行为类似于(预编译)PHP:IIS调用程序,执行它,返回值,然后完全处理掉.

但这种情况并非如此.例如,我发现静态变量在运行之间保持数据,现在我处理了所有静态变量.

因为我发现静态变量是GC的一个问题:

 internal class Helper
 {
     private static List<string> someVar = new List<string>();
     internal Helper() {
         someVar=new List<string>();
     }
     internal void someFunc(string str) {
         someVar.Add(str);
     }
     internal string[] someOtherFunc(string str) {
         string[] s = someVar.ToArray();
         someVar=new List<string>();
         return s;
     }
 }
Run Code Online (Sandbox Code Playgroud)

这里,在内存不足的情况下,someVar抛出了一个空指针错误,在我看来只能由GC引起,因为我没有发现任何代码someVar被我主动取消.

我认为内存增加速度减慢,因为我主动将最常用的控制器中的最大数组变量设置为null,但这只是一种直觉,甚至不是一个完整的解决方案.

我现在将使用您提供的链接进行一些分析,并返回一些结果.

ang*_*son 6

C#不应该有自动垃圾回收吗?

C#是.NET运行时的编程语言,.NET将自动垃圾收集带到表中.所以,是的,虽然技术上C#不是带来它的部分.

GC收集WebAPI应用程序的垃圾应该不容易吗?

当然,它应该像任何其他类型的.NET应用程序一样容易.

这里的共同主题是垃圾..NET如何确定某些东西是垃圾?通过验证没有对该对象的实时引用.老实说,我认为你更有可能错误地验证了你的一个假设,相比之下垃圾收集器中存在一个严重的错误,就是"收集那些还没有垃圾的对象".

要查找泄漏,您需要确定当前在内存中保存的对象,确定是否正确,如果没有,请确定将其保留在那里.内存分析器应用程序可以提供帮助,有许多可用的,例如Red-Gate ANTS Memory Profiler.

对于您的其他问题,如何制作符合垃圾收集条件的产品?把它变成垃圾(参见上面的定义).请注意,将局部变量设置为null可能不一定有帮助或不需要.设置一个静态变量null,但是,可能会.但确定这一点的正确方法是使用分析器.

以下是您可能会研究的一些暗中拍摄的提示:

  • 查看静态类,静态字段和静态属性.你在那里存储正在积累的数据吗?
  • 静态事件怎么样?你有这个吗?您还记得在不再需要时取消订阅该活动吗?
  • 通过"静态字段,属性和事件",我还指的是直接或间接存储在静态字段或属性中的对象中保存的普通实例字段,属性和事件.基本上,任何将对象保留在内存中的东西.
  • 你还记得你Dispose的所有IDisposable物品吗?如果没有,那么正在使用的内存可能是不受管理的.但是,通常,当垃圾收集器收集托管对象时,该对象的终结器也应该清理非托管内存,但是您可能会分配GC算法不知道的内存,因此认为它不是收集等待的大问题.有关详细信息,请参阅GC.AddMemoryPressure方法.