2014-06-10 103 views
1

我剛剛將第一個C#WebAPI應用程序交付給第一個客戶。在正常負載下,性能最初甚至比我預期的要好。原來。C#WebAPI垃圾回收

一切正常,直到在某些時候,內存已啓動並且垃圾收集開始運行暴亂(如「收集尚未垃圾的對象」)。那時,有多個W3WP線程,共有10個演唱會演唱會,每個演員只有一位數的演出。 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(); 
    } 
} 

在這種條件下,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; 
    } 
} 

這裏,低內存情況下,someVar扔了一個空指針錯誤,這在我看來只能通過GC引起的,因爲我沒有找到任何代碼,someVar被我主動取消。

我認爲內存增加速度減慢了,因爲我主動將最常用的控制器中最大的數組變量設置爲null,但這只是一種直覺,甚至不是一個完整的解決方案。

我現在將使用您提供的鏈接進行一些分析,並返回一些結果。

+6

自動垃圾收集!=我不必考慮內存管理;獲取一個內存分析器並將該應用程序配置文件查找通過什麼對象來查找*和*的對象。 –

+1

我質疑你的假設,它收集的對象不是垃圾。你如何驗證這一點?並且請注意,即使在託管內存中也很容易造成泄漏。如果您存儲對不再需要的事物的引用(事件通常是此處的罪魁禍首),則您仍會泄漏內存。要檢測內存泄漏,您應該使用專門爲此目的製作的工具,例如Red-Gate ANTS Memory Profiler等。 –

+0

請注意,由於簡單地清除指針而忘記釋放指向的內存並不是真正的問題管理內存。但保留引用你不再需要,是。 –

回答

6

不應該C#有自動垃圾收集?

C#是.NET運行時的編程語言,.NET將自動垃圾回收帶到表中。所以,是的,雖然技術上C#不是它帶來的一塊。

GC不應該很容易收集WebAPI應用程序的垃圾嗎?

當然,它應該與任何其他類型的.NET應用程序一樣簡單。

這裏的常見主題是垃圾。 .NET如何確定某件事是垃圾?通過驗證不再有對該對象的實時引用。說實話,我認爲你很可能錯誤地驗證了你的一個假設,相比之下垃圾回收器中存在一個嚴重的錯誤,就是「它收集的對象不是垃圾」。

要發現泄漏,您需要弄清楚目前內存中有哪些對象,並確定它是否正確,如果不正確,請確定它們在哪裏。一個內存分析器應用程序將有助於這一點,有許多可用的,如Red-Gate ANTS Memory Profiler

對於其他問題,如何使符合垃圾回收的條件?把它變成垃圾(見上面的定義)。請注意,將本地變量設置爲null可能不一定有幫助或不需要。將一個靜態變量設置爲null,但是,可能是。但確定的正確方法是使用分析器。

這裏有一些鏡頭,在這黑暗的類型的吸頭,你可能會考慮:

  • 看靜態類,靜態字段和靜態特性。你在那裏存儲積累的數據嗎?
  • 靜態事件怎麼樣?你有這個嗎?您是否記得在不再需要時取消訂閱活動?
  • 通過「靜態字段,屬性和事件」,我還指的是在直接或間接存儲在靜態字段或屬性中的對象中保存的常規實例字段,屬性和事件。基本上,任何會將物體留在記憶中的東西。
  • 你還記得你所有的IDisposable物品嗎?如果不是,那麼正在使用的內存可能不受管理。但是,通常情況下,當垃圾收集器收集管理對象時,該對象的終結器也應該清理非託管內存,但是您可能會分配GC算法不知道的內存,因此認爲它不是與收集等待的大問題。有關詳細信息,請參閱GC.AddMemoryPressure方法。