Ottieni nome istanza contatore prestazioni (w3wp # XX) dall'ID processo di lavoro ASP.NET
-
02-07-2019 - |
Domanda
Vorrei visualizzare alcune statistiche di memoria (working set, GC, ecc.) su una pagina Web utilizzando i contatori delle prestazioni di .NET / Process. Sfortunatamente, se ci sono più pool di applicazioni su quel server, vengono differenziati usando un indice (# 1, # 2 ecc.) Ma non so come abbinare un ID di processo (che ho) a quell'indice #xx. Esiste un modo programmatico (da una pagina Web ASP.NET)?
Soluzione
Il primo successo su Google:
Vengono visualizzati più contatori delle prestazioni CLR che hanno nomi simili a " w3wp 1 # "
Quando più processi di lavoro ASP.NET sono in esecuzione, Common Language Runtime (CLR) avranno i contatori delle prestazioni nomi che assomigliano a "W3wp # 1" o "W3sp # 2" e così via. Questo è stato risolto in .NET Framework 2.0 per includere a contatore denominato ID processo in .NET CLR Oggetto prestazioni memoria. Questo il contatore visualizza l'ID processo per un esempio. Puoi usare questo contatore per determinare il contatore delle prestazioni CLR che è associato a un processo.
Anche KB 281884 :
Per impostazione predefinita, Performance Monitor (Perfmon.msc) visualizza più processi con lo stesso nome di enumerando i processi in seguente modo:
Processo n. 1 Processo n. 2 Processo n. 3
È inoltre possibile visualizzare Performance Monitor questi processi aggiungendo il ID processo (PID) sul nome nel file seguente modo:
Process_PID
Altri suggerimenti
private static string GetProcessInstanceName(int pid)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process",
"ID Process", instance, true))
{
int val = (int) cnt.RawValue;
if (val == pid)
{
return instance;
}
}
}
throw new Exception("Could not find performance counter " +
"instance name for current process. This is truly strange ...");
}
L'esempio di chiru non funziona in un caso specifico: quando si hanno due versioni dello stesso programma, denominate uguali, una non è .net e si avvia la versione .net dopo la versione non.net. La versione .Net verrà denominata applicazione n. 1 ma quando si accede ai contatori perf CLR usando questo nome, i nomi di istanza sul contatore hanno il nome senza il numero 1, quindi si ottengono errori.
Nick.
Anche se la modifica delle impostazioni del registro sembra abbastanza facile, sfortunatamente la maggior parte di noi non ha i diritti per farlo sul server (o non vogliamo toccarlo!). In tal caso, esiste una piccola soluzione. Ho scritto un blog su questo qui .
So che ha già ricevuto una risposta, ma per motivi di lavoro completo sto pubblicando questa soluzione. Nota questo codice basato sul metodo presentato da M4N in questa catena:
public static long GetProcessPrivateWorkingSet64Size(int process_id)
{
long process_size = 0;
Process process = Process.GetProcessById(process_id);
if (process == null) return process_size;
string instanceName = GetProcessInstanceName(process.Id);
var counter = new PerformanceCounter("Process", "Working Set - Private", instanceName, true);
process_size = Convert.ToInt32(counter.NextValue()) / 1024;
return process_size;
}
public static string GetProcessInstanceName(int process_id)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true))
{
int val = (int)cnt.RawValue;
if (val == process_id)
return instance;
}
}
throw new Exception("Could not find performance counter ");
}
Inoltre, se si desidera ottenere la memoria totale di più istanze dello stesso processo, utilizzare i metodi sopra con quello seguente:
public static long GetPrivateWorkingSetForAllProcesses(string ProcessName)
{
long totalMem = 0;
Process[] process = Process.GetProcessesByName(ProcessName);
foreach (Process proc in process)
{
long memsize = GetProcessPrivateWorkingSet64Size(proc.Id);
totalMem += memsize;
}
return totalMem;
}