Add "show threadpool calls active" console debug command.

This shows named threadpool calls (excluding timer and network calls) that are currently queued or running.
Also shows total of labelled and any anonymous calls.
mb-throttle-test
Justin Clark-Casey (justincc) 2014-11-04 17:21:22 +00:00
parent 1d19e1bbd0
commit f54c70741b
3 changed files with 73 additions and 8 deletions

View File

@ -293,10 +293,16 @@ namespace OpenSim.Framework.Servers
HandleDebugThreadpoolLevel); HandleDebugThreadpoolLevel);
m_console.Commands.AddCommand( m_console.Commands.AddCommand(
"Debug", false, "show threadpool calls", "Debug", false, "show threadpool calls active",
"show threadpool calls", "show threadpool calls active",
"Show the number of labelled threadpool calls.", "Show details about threadpool calls that are still active (currently waiting or in progress)",
HandleShowThreadpoolCalls); HandleShowThreadpoolCallsActive);
m_console.Commands.AddCommand(
"Debug", false, "show threadpool calls complete",
"show threadpool calls complete",
"Show details about threadpool calls that have been completed.",
HandleShowThreadpoolCallsComplete);
m_console.Commands.AddCommand( m_console.Commands.AddCommand(
"Debug", false, "force gc", "Debug", false, "force gc",
@ -361,7 +367,36 @@ namespace OpenSim.Framework.Servers
Notice("serialosdreq is now {0}", setSerializeOsdRequests); Notice("serialosdreq is now {0}", setSerializeOsdRequests);
} }
private void HandleShowThreadpoolCalls(string module, string[] args) private void HandleShowThreadpoolCallsActive(string module, string[] args)
{
List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsInProgress().ToList();
calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));
int namedCalls = 0;
ConsoleDisplayList cdl = new ConsoleDisplayList();
foreach (KeyValuePair<string, int> kvp in calls)
{
if (kvp.Value > 0)
{
cdl.AddRow(kvp.Key, kvp.Value);
namedCalls += kvp.Value;
}
}
cdl.AddRow("TOTAL NAMED", namedCalls);
long allQueuedCalls = Util.TotalQueuedFireAndForgetCalls;
long allRunningCalls = Util.TotalRunningFireAndForgetCalls;
cdl.AddRow("TOTAL QUEUED", allQueuedCalls);
cdl.AddRow("TOTAL RUNNING", allRunningCalls);
cdl.AddRow("TOTAL ANONYMOUS", allQueuedCalls + allRunningCalls - namedCalls);
cdl.AddRow("TOTAL ALL", allQueuedCalls + allRunningCalls);
MainConsole.Instance.Output(cdl.ToString());
}
private void HandleShowThreadpoolCallsComplete(string module, string[] args)
{ {
List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsMade().ToList(); List<KeyValuePair<string, int>> calls = Util.GetFireAndForgetCallsMade().ToList();
calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value)); calls.Sort((kvp1, kvp2) => kvp2.Value.CompareTo(kvp1.Value));

View File

@ -2052,6 +2052,9 @@ namespace OpenSim.Framework
private static long numTotalThreadFuncsCalled = 0; private static long numTotalThreadFuncsCalled = 0;
private static Int32 threadFuncOverloadMode = 0; private static Int32 threadFuncOverloadMode = 0;
public static long TotalQueuedFireAndForgetCalls { get { return numQueuedThreadFuncs; } }
public static long TotalRunningFireAndForgetCalls { get { return numRunningThreadFuncs; } }
// Maps (ThreadFunc number -> Thread) // Maps (ThreadFunc number -> Thread)
private static ConcurrentDictionary<long, ThreadInfo> activeThreads = new ConcurrentDictionary<long, ThreadInfo>(); private static ConcurrentDictionary<long, ThreadInfo> activeThreads = new ConcurrentDictionary<long, ThreadInfo>();
@ -2089,6 +2092,13 @@ namespace OpenSim.Framework
private static Dictionary<string, int> m_fireAndForgetCallsMade = new Dictionary<string, int>(); private static Dictionary<string, int> m_fireAndForgetCallsMade = new Dictionary<string, int>();
public static Dictionary<string, int> GetFireAndForgetCallsInProgress()
{
return new Dictionary<string, int>(m_fireAndForgetCallsInProgress);
}
private static Dictionary<string, int> m_fireAndForgetCallsInProgress = new Dictionary<string, int>();
public static void FireAndForget(System.Threading.WaitCallback callback) public static void FireAndForget(System.Threading.WaitCallback callback)
{ {
FireAndForget(callback, null, null); FireAndForget(callback, null, null);
@ -2109,6 +2119,11 @@ namespace OpenSim.Framework
m_fireAndForgetCallsMade[context] = 1; m_fireAndForgetCallsMade[context] = 1;
else else
m_fireAndForgetCallsMade[context]++; m_fireAndForgetCallsMade[context]++;
if (!m_fireAndForgetCallsInProgress.ContainsKey(context))
m_fireAndForgetCallsInProgress[context] = 1;
else
m_fireAndForgetCallsInProgress[context]++;
} }
WaitCallback realCallback; WaitCallback realCallback;
@ -2121,7 +2136,15 @@ namespace OpenSim.Framework
if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest) if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
{ {
// If we're running regression tests, then we want any exceptions to rise up to the test code. // If we're running regression tests, then we want any exceptions to rise up to the test code.
realCallback = o => { Culture.SetCurrentCulture(); callback(o); }; realCallback =
o =>
{
Culture.SetCurrentCulture();
callback(o);
if (context != null)
m_fireAndForgetCallsInProgress[context]--;
};
} }
else else
{ {
@ -2160,6 +2183,9 @@ namespace OpenSim.Framework
activeThreads.TryRemove(threadFuncNum, out dummy); activeThreads.TryRemove(threadFuncNum, out dummy);
if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread) if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread)
m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed())); m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed()));
if (context != null)
m_fireAndForgetCallsInProgress[context]--;
} }
}; };
} }

View File

@ -110,6 +110,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
} }
/// <summary>
/// Used for processing analysis of incoming attachments in a controlled fashion.
/// </summary>
private HGIncomingSceneObjectEngine m_incomingSceneObjectEngine;
#region ISharedRegionModule #region ISharedRegionModule
public override string Name public override string Name
@ -155,6 +160,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
//scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; //scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject;
m_incomingSceneObjectEngine = new HGIncomingSceneObjectEngine(scene.Name);
m_incomingSceneObjectEngine.Start(); m_incomingSceneObjectEngine.Start();
} }
} }
@ -540,8 +546,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
} }
} }
private HGIncomingSceneObjectEngine m_incomingSceneObjectEngine = new HGIncomingSceneObjectEngine();
public override bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition) public override bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition)
{ {
// FIXME: We must make it so that we can use SOG.IsAttachment here. At the moment it is always null! // FIXME: We must make it so that we can use SOG.IsAttachment here. At the moment it is always null!