From 8a336c6860d66b9fbba6922c32e7a57fd355c57e Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 22 Oct 2009 02:28:53 +0100 Subject: [PATCH] Add MaxPoolThreads in startup to limit the size of the thread pool used for FireAndForget. This lets us limit concurrency to make OpenSim play nice --- OpenSim/Framework/Util.cs | 34 +++++++++++++------- OpenSim/Region/Application/OpenSim.cs | 2 ++ bin/OpenSim.ini.example | 3 ++ prebuild.xml | 45 ++++++++++++++------------- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index d5ae3b7ebd..9dfb75ecfd 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -41,12 +41,14 @@ using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Xml; +using System.Threading; using log4net; using Nini.Config; using Nwc.XmlRpc; using BclExtras; using OpenMetaverse; using OpenMetaverse.StructuredData; +using Amib.Threading; namespace OpenSim.Framework { @@ -55,6 +57,8 @@ namespace OpenSim.Framework /// public class Util { + private static SmartThreadPool m_ThreadPool = null; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static uint nextXferID = 5000; @@ -1293,22 +1297,28 @@ namespace OpenSim.Framework System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null); } - public static void FireAndForget(System.Threading.WaitCallback callback, object obj) + public static void SetMaxThreads(int maxThreads) { - //FireAndForgetWrapper wrapper = Singleton.GetInstance(); - //wrapper.FireAndForget(callback, obj); - System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj); + STPStartInfo startInfo = new STPStartInfo(); + startInfo.IdleTimeout = 2000; // 2 seconds + startInfo.MaxWorkerThreads = maxThreads; + startInfo.MinWorkerThreads = 5; + startInfo.StackSize = 524288; + startInfo.ThreadPriority = ThreadPriority.Normal; + + startInfo.StartSuspended = false; + + m_ThreadPool = new SmartThreadPool(startInfo); } - /*private static void EndFireAndForget(IAsyncResult ar) + public static void FireAndForget(System.Threading.WaitCallback callback, object obj) { - System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; - - try { callback.EndInvoke(ar); } - catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } - - ar.AsyncWaitHandle.Close(); - }*/ + m_ThreadPool.QueueWorkItem(new WorkItemCallback(delegate(object o) + { + callback(o); + return null; + }), obj); + } #endregion FireAndForget Threading Pattern } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 143dd2a2a0..42e2a1ea27 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -67,6 +67,8 @@ namespace OpenSim IConfig startupConfig = m_config.Source.Configs["Startup"]; + Util.SetMaxThreads(startupConfig.GetInt("MaxPoolThreads", 30)); + if (startupConfig != null) { m_startupCommandsFile = startupConfig.GetString("startup_console_commands_file", "startup_commands.txt"); diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 2d56f4eaab..92e6d91f10 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -42,6 +42,9 @@ ; Set this to the DLL containing the client stack to use. clientstack_plugin="OpenSim.Region.ClientStack.LindenUDP.dll" + ; Max threads to allocate on the FireAndForget pool + MaxPoolThreads = 30 + ; ## ; ## REGIONS ; ## diff --git a/prebuild.xml b/prebuild.xml index e17da9ad65..81f907deef 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -117,6 +117,28 @@ + + + + ../../bin/ + + + + + ../../bin/ + + + + ../../bin/ + + + + + + + + + @@ -145,6 +167,7 @@ + @@ -2387,28 +2410,6 @@ - - - - ../../bin/ - - - - - ../../bin/ - - - - ../../bin/ - - - - - - - - -