I need the code or the definition of the method getAvailableRam used in C# to find the memory usage of the computer.
class Program
{
static void Main()
{
var ramCounter = new PerformanceCounter("Memory", "Available MBytes");
Console.WriteLine("{0} Mb", ramCounter.NextValue());
}
}
Related
I have been trying to diagnose a memory leak in a service which only appears on Windows 7/Server 2008 R2. I narrowed it down to where we are using Microsoft.Web.Administration.ServerManager to gather info about the apps in our site. I whittled it down to the console app below, which exhibits the same behavior. It might still be more complex than it needs to be, but I wanted to emulate the behavior of the service as much as possible.
I found a previous question here that was very similar and made the changes suggested in the answers. This appeared to reduce the rate of growth, but it still leaks significantly (under the comments "Original Test" I have commented out code that I changed based on those answers. the "Modified Test" comments indicate the changes I made. I didn't initially have the GC.Collect call in, and when I ran this on a Windows 10 system, it grew for quite some time before the garbage collection kicked in. With the GC.Collect call in place, it ran without growing on Win 10, but on Win 7 it made no difference.
I ran it under a profiler that indicated the memory being leaked was native, and that the leak was coming from nativerd.dll.
Has anyone encountered a problem like this? I'm new to C# and am still learning how Garbage Collection works, so I'm wondering if there is something I'm doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Web.Administration;
namespace ServerManagerLeakTest
{
class Program
{
static void Main(string[] args)
{
Console.Write("Working.");
var me = new MyClass();
me.Run();
}
}
internal class MyClass
{
ServerManagerWrapper _smw = new ServerManagerWrapper();
public void Run()
{
while (true)
{
var t = Task.Run(async delegate
{
DoWork();
await Task.Delay(1000);
});
try
{
t.Wait();
}
catch (Exception e)
{
Console.Write("Main Exception: " + e.Message);
}
Console.Write(".");
}
}
public void DoWork()
{
try
{
var data = _smw.GetWebApps().ToList();
data.Clear();
}
catch (Exception e)
{
Console.Write("DoWork Exception: " + e.Message);
}
}
}
internal class ServerManagerWrapper
{
public List<int> GetWebApps()
{
List<int> result = new List<int>() { };
// Original Test
//
// using (var serverManager = new ServerManager())
// {
// foreach (var site in serverManager.Sites)
// {
// result.AddRange(GetWebApps(site));
// }
//}
// Modified Test
var serverManager = new ServerManager();
foreach (var site in serverManager.Sites)
{
result.AddRange(GetWebApps(site));
}
serverManager.Dispose();
serverManager = null;
System.GC.Collect();
return result;
}
private IEnumerable<int> GetWebApps(Site site)
{
// Original Test
//
//for (var application in site.Applications)
//{
// yield return application.GetHashCode();
//}
// Modified Test
List<int> result = new List<int>() { };
for (int i = 0; i < site.Applications.Count; i++)
{
result.Add(site.Applications[i].GetHashCode());
}
return result;
}
}
}
Answer provided in comments from #Lex Li.
Move the check to a separate process. Calling IIS REST API, PowerShell, or even appcmd and parse the result. Let the leak be out of your own service.
Im seeing some strange behavior when I access certain PerformanceCounters from within a C# application. For example when I access Process - Private Bytes it seems I get a lot of generation 2 garbage collections (the same seems to be true for other Process counters).
The below program demonstrates this. If you run it every 8 seconds or so I see a gen2 collection. If I remove the _privateBytesCounter.NextValue() I do not see any gen2 collections at all.
Can anyone explain this?
I am running Visual Sudio 2015 and targeting .NET 4.5.2.
using System;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
namespace Gen2Collections
{
class Program
{
private static PerformanceCounter _privateBytesCounter;
private static PerformanceCounter _gen2Counter;
static void Main(string[] args)
{
_privateBytesCounter = new PerformanceCounter("Process", "Private Bytes", Process.GetCurrentProcess().ProcessName);
_gen2Counter = new PerformanceCounter(".NET CLR Memory", "# Gen 2 Collections", Process.GetCurrentProcess().ProcessName);
RunMonitor();
Thread.Sleep(60000);
}
private static void RunMonitor()
{
Task.Run(() =>
{
while (true)
{
_privateBytesCounter.NextValue();
Console.WriteLine(_gen2Counter.NextValue());
Thread.Sleep(1000);
}
});
}
}
}
public static readonly PerformanceCounter theCPUCounter =
new PerformanceCounter("Processor", "% Processor Time", "_Total");
public static readonly PerformanceCounter theMemCounter =
new PerformanceCounter("Memory", "Available MBytes");
public static readonly PerformanceCounter theCPUCounterPhantomJS =
new PerformanceCounter("Processor", "% Processor Time", Process.GetProcessesByName("phantomjs").ToString());
public static void getCurrentCpuUsage()
{
Console.WriteLine(theCPUCounter.NextValue() + " %");
}
public static void getAvailableRAM()
{
Console.WriteLine(theMemCounter.NextValue() + " MB");
}
public static void getCurrentCpuUsagePhantomJS()
{
Console.WriteLine(theCPUCounterPhantomJS.NextValue() + " %");
}
I want cpu utilization data for PhantomJS browser. Here is the code that I am using. I just want to know that what parameter I can enter instead of Process.GetProcessesByName("phantomjs").ToString(). I tried many approach but it fails and gave me exception System.InvalidOperationException : Instance 'System.Diagnostics.Process[]' does not exist in the specified Category. .The name of the process is phantomjs.exe that shows in task manager. Please advice.
See the docs - this is how you should instantiate the performance counter in your case:
new PerformanceCounter(
"Process",
"% Processor Time",
"phantomjs");
Process.GetProcessesByName returns an array of processes, and so the ToString results in "System.Diagnostics.Process[]", which is not a valid instance name, not under the Processor category, and not under the Process category.
I have a simple monitoring application that is getting some values from PerfMon counters. Even when testing on the local machine, it is taking over 30 seconds to create a new PerformanceCounter object.
using System;
using System.Diagnostics;
namespace test_slow_perfmon
{
class Program
{
static void Main(string[] args)
{
Stopwatch w = new Stopwatch();
w.Start();
PerformanceCounter c = new PerformanceCounter("PhysicalDisk", "Avg. Disk Read Queue Length", "_Total", "localhost");
w.Stop();
Console.WriteLine(string.Format("Creating a counter took {0}ms", w.Elapsed.TotalMilliseconds));
}
}
}
Output from that indicates over 32s to create each counter.
What can I do (if anything) to speed up the creation of the counters?
30 seconds sounds to me suspiciously like a timeout, indicating to me that this could be some sort of network issue.
Try creating your perfmon counter using the constructor that doesn't specify a hostname and see if that helps:
PerformanceCounter c = new PerformanceCounter("PhysicalDisk", "Avg. Disk Read Queue Length", "_Total");
According to How to use .NET PerformanceCounter to track memory and CPU usage per process? PerformanceCounter should give me the number of memory usage of a given process.
According to MSDN, Process instance may also give me more or less the same number.
In order to verify my assumptions, I wrote the following code:
class Program
{
static Process process = Process.GetCurrentProcess();
static PerformanceCounter privateBytesCounter = new PerformanceCounter("Process", "Private Bytes", process.ProcessName);
static PerformanceCounter workingSetCounter = new PerformanceCounter("Process", "Working Set", process.ProcessName);
static void Main(string[] args)
{
GetMeasure();
Console.WriteLine("\nPress enter to allocate great amount of memory");
Console.ReadLine();
int[] arr = new int[10000000];
for (int i = 0; i < arr.Length; i++)
{
arr[i] = i;
}
GetMeasure();
privateBytesCounter.Dispose();
workingSetCounter.Dispose();
Console.ReadKey();
}
private static void GetMeasure()
{
Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
}
}
The output looks like
Private bytes working set
process data 22880 17516
PerformanceCounter data 21608 15608
Press enter to allocate great amount of memory
Private bytes working set
process data 22880 17516
PerformanceCounter data 21608 15608
Exactly the same! In the contrast, private bytes shown in Process Explorer increased from 32732 to 63620.
So am I doing something wrong?
You have to tell your process instance it should refresh its cached data. Data is not gathered each time you access to a property for performance purposes. You have to manually demand the data update.
private static void GetMeasure()
{
process.Refresh(); // Updates process information
Console.WriteLine("{0,38} {1,20}", "Private bytes", "working set");
Console.WriteLine("process data{0,23} {1,20}", process.PrivateMemorySize64 / 1024, process.WorkingSet64 / 1024);
Console.WriteLine("PerformanceCounter data{0,12} {1,20}", privateBytesCounter.NextValue() / 1024, workingSetCounter.NextValue() / 1024);
}
That's for your process.
For performance counters, NextValue() is supposed to retrieve a new fresh data each time, so I can't explain why it doesn't on your machine. On mine it works fine.
EDIT:
With the process.Refresh() added, here's what I get:
Private bytes working set
process data 25596 22932
PerformanceCounter data 26172 23600
Press enter to allocate great amount of memory
Private bytes working set
process data 65704 61848
PerformanceCounter data 65828 61880
Caution: my memory profiler (.NET Memory Profiler) revealed that Process.Refresh() allocates a significant chunk of memory on a temporary basis, so keep this in mind if you're reading your performance counters on a regular basis by using a timer.