diff options
-rw-r--r-- | OpenSim/Framework/Servers/ServerBase.cs | 63 | ||||
-rw-r--r-- | OpenSim/Framework/Util.cs | 104 |
2 files changed, 103 insertions, 64 deletions
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 5358444..029b848 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs | |||
@@ -667,7 +667,68 @@ namespace OpenSim.Framework.Servers | |||
667 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); | 667 | sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); |
668 | 668 | ||
669 | sb.Append("Main threadpool (excluding script engine pools)\n"); | 669 | sb.Append("Main threadpool (excluding script engine pools)\n"); |
670 | sb.Append(Util.GetThreadPoolReport()); | 670 | sb.Append(GetThreadPoolReport()); |
671 | |||
672 | return sb.ToString(); | ||
673 | } | ||
674 | |||
675 | /// <summary> | ||
676 | /// Get a thread pool report. | ||
677 | /// </summary> | ||
678 | /// <returns></returns> | ||
679 | public static string GetThreadPoolReport() | ||
680 | { | ||
681 | string threadPoolUsed = null; | ||
682 | int maxThreads = 0; | ||
683 | int minThreads = 0; | ||
684 | int allocatedThreads = 0; | ||
685 | int inUseThreads = 0; | ||
686 | int waitingCallbacks = 0; | ||
687 | int completionPortThreads = 0; | ||
688 | |||
689 | StringBuilder sb = new StringBuilder(); | ||
690 | if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | ||
691 | { | ||
692 | STPInfo stpi = Util.GetSmartThreadPoolInfo(); | ||
693 | |||
694 | // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. | ||
695 | if (stpi != null) | ||
696 | { | ||
697 | threadPoolUsed = "SmartThreadPool"; | ||
698 | maxThreads = stpi.MaxThreads; | ||
699 | minThreads = stpi.MinThreads; | ||
700 | inUseThreads = stpi.InUseThreads; | ||
701 | allocatedThreads = stpi.ActiveThreads; | ||
702 | waitingCallbacks = stpi.WaitingCallbacks; | ||
703 | } | ||
704 | } | ||
705 | else if ( | ||
706 | Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem | ||
707 | || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) | ||
708 | { | ||
709 | threadPoolUsed = "BuiltInThreadPool"; | ||
710 | ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); | ||
711 | ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); | ||
712 | int availableThreads; | ||
713 | ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); | ||
714 | inUseThreads = maxThreads - availableThreads; | ||
715 | allocatedThreads = -1; | ||
716 | waitingCallbacks = -1; | ||
717 | } | ||
718 | |||
719 | if (threadPoolUsed != null) | ||
720 | { | ||
721 | sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); | ||
722 | sb.AppendFormat("Max threads : {0}\n", maxThreads); | ||
723 | sb.AppendFormat("Min threads : {0}\n", minThreads); | ||
724 | sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); | ||
725 | sb.AppendFormat("In use threads : {0}\n", inUseThreads); | ||
726 | sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); | ||
727 | } | ||
728 | else | ||
729 | { | ||
730 | sb.AppendFormat("Thread pool not used\n"); | ||
731 | } | ||
671 | 732 | ||
672 | return sb.ToString(); | 733 | return sb.ToString(); |
673 | } | 734 | } |
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 5e5eb7e..ba6cc75 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs | |||
@@ -89,9 +89,30 @@ namespace OpenSim.Framework | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /// <summary> | 91 | /// <summary> |
92 | /// Class for delivering SmartThreadPool statistical information | ||
93 | /// </summary> | ||
94 | /// <remarks> | ||
95 | /// We do it this way so that we do not directly expose STP. | ||
96 | /// </remarks> | ||
97 | public class STPInfo | ||
98 | { | ||
99 | public string Name { get; set; } | ||
100 | public STPStartInfo STPStartInfo { get; set; } | ||
101 | public WIGStartInfo WIGStartInfo { get; set; } | ||
102 | public bool IsIdle { get; set; } | ||
103 | public bool IsShuttingDown { get; set; } | ||
104 | public int MaxThreads { get; set; } | ||
105 | public int MinThreads { get; set; } | ||
106 | public int InUseThreads { get; set; } | ||
107 | public int ActiveThreads { get; set; } | ||
108 | public int WaitingCallbacks { get; set; } | ||
109 | public int MaxConcurrentWorkItems { get; set; } | ||
110 | } | ||
111 | |||
112 | /// <summary> | ||
92 | /// Miscellaneous utility functions | 113 | /// Miscellaneous utility functions |
93 | /// </summary> | 114 | /// </summary> |
94 | public class Util | 115 | public static class Util |
95 | { | 116 | { |
96 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 117 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
97 | 118 | ||
@@ -1852,74 +1873,31 @@ namespace OpenSim.Framework | |||
1852 | } | 1873 | } |
1853 | 1874 | ||
1854 | /// <summary> | 1875 | /// <summary> |
1855 | /// Get a thread pool report. | 1876 | /// Get information about the current state of the smart thread pool. |
1856 | /// </summary> | 1877 | /// </summary> |
1857 | /// <returns></returns> | 1878 | /// <returns> |
1858 | public static string GetThreadPoolReport() | 1879 | /// null if this isn't the pool being used for non-scriptengine threads. |
1880 | /// </returns> | ||
1881 | public static STPInfo GetSmartThreadPoolInfo() | ||
1859 | { | 1882 | { |
1860 | string threadPoolUsed = null; | 1883 | if (m_ThreadPool == null) |
1861 | int maxThreads = 0; | 1884 | return null; |
1862 | int minThreads = 0; | ||
1863 | int allocatedThreads = 0; | ||
1864 | int inUseThreads = 0; | ||
1865 | int waitingCallbacks = 0; | ||
1866 | int completionPortThreads = 0; | ||
1867 | |||
1868 | StringBuilder sb = new StringBuilder(); | ||
1869 | if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) | ||
1870 | { | ||
1871 | // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool. | ||
1872 | if (m_ThreadPool != null) | ||
1873 | { | ||
1874 | threadPoolUsed = "SmartThreadPool"; | ||
1875 | maxThreads = m_ThreadPool.MaxThreads; | ||
1876 | minThreads = m_ThreadPool.MinThreads; | ||
1877 | inUseThreads = m_ThreadPool.InUseThreads; | ||
1878 | allocatedThreads = m_ThreadPool.ActiveThreads; | ||
1879 | waitingCallbacks = m_ThreadPool.WaitingCallbacks; | ||
1880 | } | ||
1881 | } | ||
1882 | else if ( | ||
1883 | FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem | ||
1884 | || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) | ||
1885 | { | ||
1886 | threadPoolUsed = "BuiltInThreadPool"; | ||
1887 | ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); | ||
1888 | ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); | ||
1889 | int availableThreads; | ||
1890 | ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); | ||
1891 | inUseThreads = maxThreads - availableThreads; | ||
1892 | allocatedThreads = -1; | ||
1893 | waitingCallbacks = -1; | ||
1894 | } | ||
1895 | 1885 | ||
1896 | if (threadPoolUsed != null) | 1886 | STPInfo stpi = new STPInfo(); |
1897 | { | 1887 | stpi.Name = m_ThreadPool.Name; |
1898 | sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); | 1888 | stpi.STPStartInfo = m_ThreadPool.STPStartInfo; |
1899 | sb.AppendFormat("Max threads : {0}\n", maxThreads); | 1889 | stpi.IsIdle = m_ThreadPool.IsIdle; |
1900 | sb.AppendFormat("Min threads : {0}\n", minThreads); | 1890 | stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown; |
1901 | sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString()); | 1891 | stpi.MaxThreads = m_ThreadPool.MaxThreads; |
1902 | sb.AppendFormat("In use threads : {0}\n", inUseThreads); | 1892 | stpi.MinThreads = m_ThreadPool.MinThreads; |
1903 | sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString()); | 1893 | stpi.InUseThreads = m_ThreadPool.InUseThreads; |
1904 | } | 1894 | stpi.ActiveThreads = m_ThreadPool.ActiveThreads; |
1905 | else | 1895 | stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks; |
1906 | { | 1896 | stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency; |
1907 | sb.AppendFormat("Thread pool not used\n"); | ||
1908 | } | ||
1909 | 1897 | ||
1910 | return sb.ToString(); | 1898 | return stpi; |
1911 | } | 1899 | } |
1912 | 1900 | ||
1913 | // private static object SmartThreadPoolCallback(object o) | ||
1914 | // { | ||
1915 | // object[] array = (object[])o; | ||
1916 | // WaitCallback callback = (WaitCallback)array[0]; | ||
1917 | // object obj = array[1]; | ||
1918 | // | ||
1919 | // callback(obj); | ||
1920 | // return null; | ||
1921 | // } | ||
1922 | |||
1923 | #endregion FireAndForget Threading Pattern | 1901 | #endregion FireAndForget Threading Pattern |
1924 | 1902 | ||
1925 | /// <summary> | 1903 | /// <summary> |