There's probably 20 (or more?) of these questions on stackoverflow, but none of them address what I'm trying to do.
I have an application whose purpose is to receive some data from an outside source through a web service, normalize it and then populate it into a BlockingCollection<T>
, to be consumed at a later time when a connection to another web service can be made. The code to receive the data looks like this (it's a Nancy callback):
private dynamic AcceptSignalData(dynamic parameters)
{
try
{
//This call extracts the post body data from the web request.
//The post body data contains JSON of the changed signals
var states = this.Bind< List< SignalStateData > >();
this._logger.Log(LogSeverity.Debug, string.Format("Received {0} states", states.Count));
foreach (var state in states.Select(s => new SignalStateData(s.Id, s.Value, s.Timestamp.ToUniversalTime())))
{
this._collection.Add(state);
}
return this.Response.AsJson(true);
}
catch (Exception ex)
{
this._logger.Log(LogSeverity.Error, "An error was thrown while extracting received data. The error is as follows:");
this._logger.Log(LogSeverity.Error, ex);
}
return this.Response.AsJson(false);
}
In this case, this._collection
is consumed if a connection to the other web service can be made.
A requirement of this is: if the connection cannot be made, the application should simply hold on to the data in this._collection
until the cows come home and dispatch when the connection is there. Obviously if it waits to long the application will throw an OutOfMemoryException
which is the problem I'm running into.
I'm trying to determine the point at which the OutOfMemoryException
will actually occur so I can simply drop the n oldest items from this._collection
. I want to find, as a rough percentage, how much memory my process has remaining.
I've used the code from this SO answer but from my understanding, that's the total memory available in the system, which isn't all that useful for my purpose. This is the code I have now, but it produces negative numbers because of the system-wide scope of PerformanceCounter
:
/// <summary>
/// The constructor for the <see cref="MemoryManager" /> object.
/// </summary>
public MemoryManager(ILogger logger)
{
this._memoryCounter = new PerformanceCounter("Memory", "Available Bytes");
this._memoryCancellationToken = new CancellationTokenSource();
this._updateMemoryTask = Task.Factory.StartNew(this.UpdateAvailableMemory, this._memoryCancellationToken.Token);
this._currentProcess = Process.GetCurrentProcess();
this._logger = logger;
this.AvailableMemoryPercentage = 100.0F;
}
#endregion
#region Methods
private async void UpdateAvailableMemory(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
try
{
float totalAvailableBytes = this._memoryCounter.NextValue();
float totalUsedBytes = totalAvailableBytes - this._currentProcess.PrivateMemorySize64;
this.AvailableMemoryPercentage = Math.Round(totalUsedBytes / totalAvailableBytes * 100, 2);
var logMessage = string.Format("RAM: {0} MB ({1}%)",
(1.0 * totalUsedBytes / 1024 / 1024).ToString("0.##"),
this.AvailableMemoryPercentage);
this._logger.Log(LogSeverity.Info, logMessage);
await Task.Delay(MEMORYCHECKINTERVAL_MS, token);
}
catch (Exception ex)
{
this._logger.Log(LogSeverity.Debug, "Exception in memory management:");
this._logger.Log(LogSeverity.Debug, ex);
}
}
}
I don't care how much memory my process is using (well, I guess I do but it's only 50% of the problem); I'm more interested in how much is available. I understand that there's a lot of different angles to this but I'm looking for a very rough estimate.