refactor: Move existing code to generate report information on the threadpool to the ServerBase rather than being in Util

cpu-performance
Justin Clark-Casey (justincc) 2013-06-17 23:57:10 +01:00
parent c0a00cd7fd
commit b7c9dee033
2 changed files with 103 additions and 64 deletions

View File

@ -667,7 +667,68 @@ namespace OpenSim.Framework.Servers
sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
sb.Append("Main threadpool (excluding script engine pools)\n"); sb.Append("Main threadpool (excluding script engine pools)\n");
sb.Append(Util.GetThreadPoolReport()); sb.Append(GetThreadPoolReport());
return sb.ToString();
}
/// <summary>
/// Get a thread pool report.
/// </summary>
/// <returns></returns>
public static string GetThreadPoolReport()
{
string threadPoolUsed = null;
int maxThreads = 0;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
StringBuilder sb = new StringBuilder();
if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
{
STPInfo stpi = Util.GetSmartThreadPoolInfo();
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
if (stpi != null)
{
threadPoolUsed = "SmartThreadPool";
maxThreads = stpi.MaxThreads;
minThreads = stpi.MinThreads;
inUseThreads = stpi.InUseThreads;
allocatedThreads = stpi.ActiveThreads;
waitingCallbacks = stpi.WaitingCallbacks;
}
}
else if (
Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
|| Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
if (threadPoolUsed != null)
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString(); return sb.ToString();
} }

View File

@ -88,10 +88,31 @@ namespace OpenSim.Framework
Thread, Thread,
} }
/// <summary>
/// Class for delivering SmartThreadPool statistical information
/// </summary>
/// <remarks>
/// We do it this way so that we do not directly expose STP.
/// </remarks>
public class STPInfo
{
public string Name { get; set; }
public STPStartInfo STPStartInfo { get; set; }
public WIGStartInfo WIGStartInfo { get; set; }
public bool IsIdle { get; set; }
public bool IsShuttingDown { get; set; }
public int MaxThreads { get; set; }
public int MinThreads { get; set; }
public int InUseThreads { get; set; }
public int ActiveThreads { get; set; }
public int WaitingCallbacks { get; set; }
public int MaxConcurrentWorkItems { get; set; }
}
/// <summary> /// <summary>
/// Miscellaneous utility functions /// Miscellaneous utility functions
/// </summary> /// </summary>
public class Util public static class Util
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -1852,74 +1873,31 @@ namespace OpenSim.Framework
} }
/// <summary> /// <summary>
/// Get a thread pool report. /// Get information about the current state of the smart thread pool.
/// </summary> /// </summary>
/// <returns></returns> /// <returns>
public static string GetThreadPoolReport() /// null if this isn't the pool being used for non-scriptengine threads.
/// </returns>
public static STPInfo GetSmartThreadPoolInfo()
{ {
string threadPoolUsed = null; if (m_ThreadPool == null)
int maxThreads = 0; return null;
int minThreads = 0;
int allocatedThreads = 0;
int inUseThreads = 0;
int waitingCallbacks = 0;
int completionPortThreads = 0;
StringBuilder sb = new StringBuilder(); STPInfo stpi = new STPInfo();
if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) stpi.Name = m_ThreadPool.Name;
{ stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
// ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. stpi.IsIdle = m_ThreadPool.IsIdle;
if (m_ThreadPool != null) stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
{ stpi.MaxThreads = m_ThreadPool.MaxThreads;
threadPoolUsed = "SmartThreadPool"; stpi.MinThreads = m_ThreadPool.MinThreads;
maxThreads = m_ThreadPool.MaxThreads; stpi.InUseThreads = m_ThreadPool.InUseThreads;
minThreads = m_ThreadPool.MinThreads; stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
inUseThreads = m_ThreadPool.InUseThreads; stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
allocatedThreads = m_ThreadPool.ActiveThreads; stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
waitingCallbacks = m_ThreadPool.WaitingCallbacks;
}
}
else if (
FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
|| FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
{
threadPoolUsed = "BuiltInThreadPool";
ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
int availableThreads;
ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
inUseThreads = maxThreads - availableThreads;
allocatedThreads = -1;
waitingCallbacks = -1;
}
if (threadPoolUsed != null) return stpi;
{
sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
sb.AppendFormat("Max threads : {0}\n", maxThreads);
sb.AppendFormat("Min threads : {0}\n", minThreads);
sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
sb.AppendFormat("In use threads : {0}\n", inUseThreads);
sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
}
else
{
sb.AppendFormat("Thread pool not used\n");
}
return sb.ToString();
} }
// private static object SmartThreadPoolCallback(object o)
// {
// object[] array = (object[])o;
// WaitCallback callback = (WaitCallback)array[0];
// object obj = array[1];
//
// callback(obj);
// return null;
// }
#endregion FireAndForget Threading Pattern #endregion FireAndForget Threading Pattern
/// <summary> /// <summary>