簡體   English   中英

進程內存大小 - 不同的計數器

[英]Process Memory Size - Different Counters

我試圖找出我自己的.Net服務器進程正在使用多少內存(用於監視和記錄目的)。

我正在使用:

Process.GetCurrentProcess().PrivateMemorySize64

但是,Process對象有幾個不同的屬性,讓我可以讀取使用的內存空間:Paged,NonPaged,PagedSystem,NonPagedSystem,Private,Virtual,WorkingSet

然后是“峰值”:我猜測它只存儲了最后一次所用的最大值。

閱讀每個屬性的MSDN定義對我來說並沒有太大幫助。 我不得不承認我對內存管理方式的了解(就分頁和虛擬內容而言)非常有限。

所以我的問題顯然是“我應該使用哪一個?”,我知道答案是“它取決於”。

這個過程基本上會在內存中保存一堆列表,而其他進程與之通信並查詢它。 我期望運行它的服務器需要大量的RAM,因此我會隨着時間的推移查詢這些數據,以便能夠估計RAM要求與其保留的列表大小相比較。

那么......我應該使用哪一個?為什么?

如果您想知道GC使用了多少嘗試:

GC.GetTotalMemory(true)

如果您想知道您的進程從Windows使用的內容(TaskManager中的VM Size列),請嘗試:

Process.GetCurrentProcess().PrivateMemorySize64

如果你想知道你的進程在RAM中的位置(而不是在頁面文件中)(TaskManager中的Mem Usage列),請嘗試:

Process.GetCurrentProcess().WorkingSet64

有關不同類型的內存的更多說明,請參見此處

好吧,我通過Google找到了Lars提到的同一頁面,我相信這對於那些不太了解記憶效果的人來說是一個很好的解釋(就像我一樣)。

http://shsc.info/WindowsMemoryManagement

我的簡短結論是:

  • Private Bytes =我的進程請求存儲數據的內存。 其中一些可能會被分頁到磁盤。 這是我正在尋找的信息。

  • 虛擬字節數=私有字節數,加上與加載的DLL等的其他進程共享的空間。

  • Working Set =我的進程的所有內存中未被分頁到磁盤的部分。 所以分頁到磁盤的數量應該是(虛擬 - 工作集)。

感謝你的幫助!

如果要使用Windows Vista任務管理器中顯示的“內存(專用工作集)”,它等同於Process Explorer“WS Private Bytes”,則代碼如下所示。 可能最好將這個無限循環拋在一個線程/后台任務中,用於實時統計。

using System.Threading;
using System.Diagnostics;

//namespace...class...method

Process thisProc = Process.GetCurrentProcess();
PerformanceCounter PC = new PerformanceCounter();

PC.CategoryName = "Process";
PC.CounterName = "Working Set - Private";
PC.InstanceName = thisProc.ProcessName;

while (true)
{
 String privMemory = (PC.NextValue()/1000).ToString()+"KB (Private Bytes)";
 //Do something with string privMemory

 Thread.Sleep(1000);
}

為了獲得任務管理器給出的價值,我的帽子將由Mike Regan的解決方案提供。 但是,一個改變:它不是: perfCounter.NextValue()/1000; 但是perfCounter.NextValue()/1024; (即一個真正的千字節)。 這給出了您在任務管理器中看到的確切值。

以下是在WPF或WinForms應用程序中以簡單方式顯示“內存使用”(任務管理器,如給定)的完整解決方案(在本例中,僅在標題中)。 只需在新的Window構造函數中調用此方法:

    private void DisplayMemoryUsageInTitleAsync()
    {
        origWindowTitle = this.Title; // set WinForms or WPF Window Title to field
        BackgroundWorker wrkr = new BackgroundWorker();
        wrkr.WorkerReportsProgress = true;

        wrkr.DoWork += (object sender, DoWorkEventArgs e) => {
            Process currProcess = Process.GetCurrentProcess();
            PerformanceCounter perfCntr = new PerformanceCounter();
            perfCntr.CategoryName = "Process";
            perfCntr.CounterName = "Working Set - Private";
            perfCntr.InstanceName = currProcess.ProcessName;

            while (true)
            {
                int value = (int)perfCntr.NextValue() / 1024;
                string privateMemoryStr = value.ToString("n0") + "KB [Private Bytes]";
                wrkr.ReportProgress(0, privateMemoryStr);
                Thread.Sleep(1000);
            }
        };

        wrkr.ProgressChanged += (object sender, ProgressChangedEventArgs e) => {
            string val = e.UserState as string;
            if (!string.IsNullOrEmpty(val))
                this.Title = string.Format(@"{0}   ({1})", origWindowTitle, val);
        };

        wrkr.RunWorkerAsync();
    }`

工作集不是一個好用的屬性。 從我收集的內容中,它包括進程可以觸及的所有內容,甚至是由多個進程共享的庫,因此您在該計數器中看到了雙重計數的字節。 私人記憶是一個更好的反擊。

我建議還要監控頁面故障發生的頻率。 當您嘗試訪問已從物理內存移動到交換文件的某些數據時,會發生頁面故障,並且系統必須先從磁盤讀取頁面,然后才能訪問此數據。

這是一個公平的描述嗎? 我想與我的團隊分享這個,所以如果不正確(或不完整),請告訴我:

C#有幾種方法可以詢問我的進程使用了​​多少內存。

  • 可以管理(通過CLR)或不管理分配的內存。
  • 分配的內存可以是虛擬的(存儲在磁盤上)或加載(到RAM頁面中)
  • 分配的內存可以是私有的(僅由進程使用)或共享的(例如,屬於其他進程正在引用的DLL)。

鑒於上述情況,以下是一些測量C#內存使用情況的方法:

1)Process.VirtualMemorySize64():返回進程使用的所有內存 - 托管或非托管,虛擬或加載,私有或共享。

2)Process.PrivateMemorySize64():返回進程使用的所有私有內存 - 托管或非托管,虛擬或加載。

3)Process.WorkingSet64():返回進程使用的所有私有,已加載的內存 - 托管或非托管

4)GC.GetTotalMemory():返回垃圾收集器正在監視的托管內存量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM