Skip to content

Instantly share code, notes, and snippets.

@martinrayenglish
Created September 20, 2020 12:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinrayenglish/b084bdb7efb2779f63fcb7c7b60b84b0 to your computer and use it in GitHub Desktop.
Save martinrayenglish/b084bdb7efb2779f63fcb7c7b60b84b0 to your computer and use it in GitHub Desktop.
Sitecore Thread Pool Size Monitor
using Sitecore.Abstractions;
using Sitecore.Framework.Conditions;
using System;
using System.Threading;
namespace Sitecore.Analytics
{
internal class ThreadPoolSizeMonitor : IThreadPoolSizeMonitor, IDisposable
{
private readonly int _accelerationRate;
private readonly int _decelerationRate;
private readonly TimeSpan _updateInterval;
private readonly BaseLog _log;
private bool _disposed;
public ThreadPoolSizeMonitor(
int accelerationRate,
int decelerationRate,
TimeSpan updateInterval,
BaseLog log)
{
Condition.Requires<int>(accelerationRate, nameof (accelerationRate)).IsGreaterThan(0);
Condition.Requires<int>(decelerationRate, nameof (decelerationRate)).IsGreaterThan(0);
Condition.Requires<BaseLog>(log, nameof (log)).IsNotNull<BaseLog>();
this._accelerationRate = accelerationRate;
this._decelerationRate = decelerationRate;
this._updateInterval = updateInterval;
this._log = log;
this._log.Info(string.Format("Initialized ThreadPoolSizeMonitor with parameters accelerationRate: {0}, decelerationRate: {1}, updateInterval: {2}", (object) this._accelerationRate, (object) this._decelerationRate, (object) this._updateInterval), (object) this);
}
public void Start()
{
this._log.Info("Start thread pool size monitor in the background", (object) this);
new Thread(new ThreadStart(this.Monitor))
{
IsBackground = true
}.Start();
}
public void Stop()
{
this.Dispose();
}
public void Dispose()
{
this._disposed = true;
}
private void Monitor()
{
while (!this._disposed)
{
try
{
int workerThreads1;
ThreadPool.GetAvailableThreads(out workerThreads1, out int _);
int workerThreads2;
int completionPortThreads;
ThreadPool.GetMinThreads(out workerThreads2, out completionPortThreads);
int workerThreads3;
ThreadPool.GetMaxThreads(out workerThreads3, out int _);
int num1 = workerThreads3 - workerThreads1;
int processorCount = System.Environment.ProcessorCount;
int num2 = num1 >= processorCount ? this._accelerationRate * (int) Math.Round((double) num1 / (double) this._accelerationRate) + this._accelerationRate : processorCount;
if (num2 >= workerThreads2 && num2 < workerThreads3 - 10)
{
if (num2 != workerThreads2)
{
workerThreads2 = num2;
ThreadPool.SetMinThreads(workerThreads2, completionPortThreads);
this._log.Debug(string.Format("Increased min threads to {0}", (object) workerThreads2), (object) this);
}
}
else if (num2 < workerThreads2)
{
workerThreads2 -= this._decelerationRate;
ThreadPool.SetMinThreads(workerThreads2, completionPortThreads);
this._log.Debug(string.Format("Cooling down. {0} threads are active", (object) workerThreads2), (object) this);
}
this._log.Debug(string.Format("Min threads: {0}, Active threads: {1}.", (object) workerThreads2, (object) (workerThreads3 - workerThreads1)), (object) this);
}
catch (Exception ex)
{
this._log.Error("Exception occured in ThreadPoolSizeMonitor", ex, (object) this);
}
Thread.Sleep(this._updateInterval);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment