diff options
author | Justin Clark-Casey (justincc) | 2012-10-11 23:28:53 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-10-11 23:28:53 +0100 |
commit | 1f2472d0fcd86a7ae09c01ecb3508eab001ce033 (patch) | |
tree | 2668a8dc7ede987d1b104292508c311c03a37e59 /OpenSim | |
parent | Assign endVector before control leaves ObjectCommandsModule.TryParseVectorRan... (diff) | |
download | opensim-SC-1f2472d0fcd86a7ae09c01ecb3508eab001ce033.zip opensim-SC-1f2472d0fcd86a7ae09c01ecb3508eab001ce033.tar.gz opensim-SC-1f2472d0fcd86a7ae09c01ecb3508eab001ce033.tar.bz2 opensim-SC-1f2472d0fcd86a7ae09c01ecb3508eab001ce033.tar.xz |
Extend "show stats" command to "show stats [list|all|<category name>]"
This allows different categories of stats to be shown, with options to list categories or show all stats.
Currently categories are scene and simulator and only a very few stats are currently registered via this mechanism.
This commit also adds percentage stats for packets and blocks reused from the packet pool.
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | 16 | ||||
-rw-r--r-- | OpenSim/Framework/Monitoring/StatsManager.cs | 193 | ||||
-rw-r--r-- | OpenSim/Framework/Servers/BaseOpenSimServer.cs | 32 | ||||
-rw-r--r-- | OpenSim/Region/Application/OpenSimBase.cs | 72 | ||||
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | 43 |
5 files changed, 259 insertions, 97 deletions
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index 8ac9090..aa86202 100644 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -359,13 +359,19 @@ Asset service request failures: {3}" + Environment.NewLine, | |||
359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, | 359 | inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, |
360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); | 360 | netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); |
361 | 361 | ||
362 | foreach (KeyValuePair<string, Stat> kvp in StatsManager.RegisteredStats) | 362 | Dictionary<string, Dictionary<string, Stat>> sceneStats; |
363 | { | ||
364 | Stat stat = kvp.Value; | ||
365 | 363 | ||
366 | if (stat.Category == "scene" && stat.Verbosity == StatVerbosity.Info) | 364 | if (StatsManager.TryGetStats("scene", out sceneStats)) |
365 | { | ||
366 | foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats) | ||
367 | { | 367 | { |
368 | sb.AppendFormat("Slow frames ({0}): {1}\n", stat.Container, stat.Value); | 368 | foreach (Stat stat in kvp.Value.Values) |
369 | { | ||
370 | if (stat.Verbosity == StatVerbosity.Info) | ||
371 | { | ||
372 | sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName); | ||
373 | } | ||
374 | } | ||
369 | } | 375 | } |
370 | } | 376 | } |
371 | 377 | ||
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index b5dc24f..a67c5f8 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using OpenSim.Framework.Console; | ||
30 | 31 | ||
31 | namespace OpenSim.Framework.Monitoring | 32 | namespace OpenSim.Framework.Monitoring |
32 | { | 33 | { |
@@ -35,13 +36,23 @@ namespace OpenSim.Framework.Monitoring | |||
35 | /// </summary> | 36 | /// </summary> |
36 | public class StatsManager | 37 | public class StatsManager |
37 | { | 38 | { |
39 | // Subcommand used to list other stats. | ||
40 | public const string AllSubCommand = "all"; | ||
41 | |||
42 | // Subcommand used to list other stats. | ||
43 | public const string ListSubCommand = "list"; | ||
44 | |||
45 | // All subcommands | ||
46 | public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand }; | ||
47 | |||
38 | /// <summary> | 48 | /// <summary> |
39 | /// Registered stats. | 49 | /// Registered stats categorized by category/container/shortname |
40 | /// </summary> | 50 | /// </summary> |
41 | /// <remarks> | 51 | /// <remarks> |
42 | /// Do not add or remove from this dictionary. | 52 | /// Do not add or remove directly from this dictionary. |
43 | /// </remarks> | 53 | /// </remarks> |
44 | public static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>(); | 54 | public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats |
55 | = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>(); | ||
45 | 56 | ||
46 | private static AssetStatsCollector assetStats; | 57 | private static AssetStatsCollector assetStats; |
47 | private static UserStatsCollector userStats; | 58 | private static UserStatsCollector userStats; |
@@ -51,6 +62,76 @@ namespace OpenSim.Framework.Monitoring | |||
51 | public static UserStatsCollector UserStats { get { return userStats; } } | 62 | public static UserStatsCollector UserStats { get { return userStats; } } |
52 | public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } | 63 | public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } |
53 | 64 | ||
65 | public static void RegisterConsoleCommands(CommandConsole console) | ||
66 | { | ||
67 | console.Commands.AddCommand( | ||
68 | "General", | ||
69 | false, | ||
70 | "show stats", | ||
71 | "show stats [list|all|<category>]", | ||
72 | "Show statistical information for this server", | ||
73 | "If no final argument is specified then legacy statistics information is currently shown.\n" | ||
74 | + "If list is specified then statistic categories are shown.\n" | ||
75 | + "If all is specified then all registered statistics are shown.\n" | ||
76 | + "If a category name is specified then only statistics from that category are shown.\n" | ||
77 | + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", | ||
78 | HandleShowStatsCommand); | ||
79 | } | ||
80 | |||
81 | public static void HandleShowStatsCommand(string module, string[] cmd) | ||
82 | { | ||
83 | ICommandConsole con = MainConsole.Instance; | ||
84 | |||
85 | if (cmd.Length > 2) | ||
86 | { | ||
87 | var categoryName = cmd[2]; | ||
88 | |||
89 | if (categoryName == AllSubCommand) | ||
90 | { | ||
91 | foreach (var category in RegisteredStats.Values) | ||
92 | { | ||
93 | OutputCategoryStatsToConsole(con, category); | ||
94 | } | ||
95 | } | ||
96 | else if (categoryName == ListSubCommand) | ||
97 | { | ||
98 | con.Output("Statistic categories available are:"); | ||
99 | foreach (string category in RegisteredStats.Keys) | ||
100 | con.OutputFormat(" {0}", category); | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | Dictionary<string, Dictionary<string, Stat>> category; | ||
105 | if (!RegisteredStats.TryGetValue(categoryName, out category)) | ||
106 | { | ||
107 | con.OutputFormat("No such category as {0}", categoryName); | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | OutputCategoryStatsToConsole(con, category); | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | // Legacy | ||
118 | con.Output(SimExtraStats.Report()); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | private static void OutputCategoryStatsToConsole( | ||
123 | ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category) | ||
124 | { | ||
125 | foreach (var container in category.Values) | ||
126 | { | ||
127 | foreach (Stat stat in container.Values) | ||
128 | { | ||
129 | con.OutputFormat( | ||
130 | "{0}.{1}.{2} : {3}{4}", stat.Category, stat.Container, stat.ShortName, stat.Value, stat.UnitName); | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
54 | /// <summary> | 135 | /// <summary> |
55 | /// Start collecting statistics related to assets. | 136 | /// Start collecting statistics related to assets. |
56 | /// Should only be called once. | 137 | /// Should only be called once. |
@@ -73,43 +154,100 @@ namespace OpenSim.Framework.Monitoring | |||
73 | return userStats; | 154 | return userStats; |
74 | } | 155 | } |
75 | 156 | ||
157 | /// <summary> | ||
158 | /// Registers a statistic. | ||
159 | /// </summary> | ||
160 | /// <param name='stat'></param> | ||
161 | /// <returns></returns> | ||
76 | public static bool RegisterStat(Stat stat) | 162 | public static bool RegisterStat(Stat stat) |
77 | { | 163 | { |
164 | Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; | ||
165 | Dictionary<string, Stat> container = null, newContainer; | ||
166 | |||
78 | lock (RegisteredStats) | 167 | lock (RegisteredStats) |
79 | { | 168 | { |
80 | if (RegisteredStats.ContainsKey(stat.UniqueName)) | 169 | // Stat name is not unique across category/container/shortname key. |
81 | { | 170 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests |
82 | // XXX: For now just return false. This is to avoid problems in regression tests where all tests | 171 | // in a class are run in the same instance of the VM. |
83 | // in a class are run in the same instance of the VM. | 172 | if (TryGetStat(stat, out category, out container)) |
84 | return false; | 173 | return false; |
85 | 174 | ||
86 | // throw new Exception( | 175 | // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. |
87 | // "StatsManager already contains stat with ShortName {0} in Category {1}", stat.ShortName, stat.Category); | 176 | // This means that we don't need to lock or copy them on iteration, which will be a much more |
88 | } | 177 | // common operation after startup. |
178 | if (container != null) | ||
179 | newContainer = new Dictionary<string, Stat>(container); | ||
180 | else | ||
181 | newContainer = new Dictionary<string, Stat>(); | ||
182 | |||
183 | if (category != null) | ||
184 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); | ||
185 | else | ||
186 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(); | ||
89 | 187 | ||
90 | // We take a replace-on-write approach here so that we don't need to generate a new Dictionary | 188 | newContainer[stat.ShortName] = stat; |
91 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | 189 | newCategory[stat.Container] = newContainer; |
92 | newRegisteredStats[stat.UniqueName] = stat; | 190 | RegisteredStats[stat.Category] = newCategory; |
93 | RegisteredStats = newRegisteredStats; | ||
94 | } | 191 | } |
95 | 192 | ||
96 | return true; | 193 | return true; |
97 | } | 194 | } |
98 | 195 | ||
196 | /// <summary> | ||
197 | /// Deregister a statistic | ||
198 | /// </summary>> | ||
199 | /// <param name='stat'></param> | ||
200 | /// <returns></returns | ||
99 | public static bool DeregisterStat(Stat stat) | 201 | public static bool DeregisterStat(Stat stat) |
100 | { | 202 | { |
203 | Dictionary<string, Dictionary<string, Stat>> category = null, newCategory; | ||
204 | Dictionary<string, Stat> container = null, newContainer; | ||
205 | |||
101 | lock (RegisteredStats) | 206 | lock (RegisteredStats) |
102 | { | 207 | { |
103 | if (!RegisteredStats.ContainsKey(stat.UniqueName)) | 208 | if (!TryGetStat(stat, out category, out container)) |
104 | return false; | 209 | return false; |
105 | 210 | ||
106 | Dictionary<string, Stat> newRegisteredStats = new Dictionary<string, Stat>(RegisteredStats); | 211 | newContainer = new Dictionary<string, Stat>(container); |
107 | newRegisteredStats.Remove(stat.UniqueName); | 212 | newContainer.Remove(stat.UniqueName); |
108 | RegisteredStats = newRegisteredStats; | 213 | |
214 | newCategory = new Dictionary<string, Dictionary<string, Stat>>(category); | ||
215 | newCategory.Remove(stat.Container); | ||
216 | |||
217 | newCategory[stat.Container] = newContainer; | ||
218 | RegisteredStats[stat.Category] = newCategory; | ||
109 | 219 | ||
110 | return true; | 220 | return true; |
111 | } | 221 | } |
112 | } | 222 | } |
223 | |||
224 | public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats) | ||
225 | { | ||
226 | return RegisteredStats.TryGetValue(category, out stats); | ||
227 | } | ||
228 | |||
229 | public static bool TryGetStat( | ||
230 | Stat stat, | ||
231 | out Dictionary<string, Dictionary<string, Stat>> category, | ||
232 | out Dictionary<string, Stat> container) | ||
233 | { | ||
234 | category = null; | ||
235 | container = null; | ||
236 | |||
237 | lock (RegisteredStats) | ||
238 | { | ||
239 | if (RegisteredStats.TryGetValue(stat.Category, out category)) | ||
240 | { | ||
241 | if (category.TryGetValue(stat.Container, out container)) | ||
242 | { | ||
243 | if (container.ContainsKey(stat.ShortName)) | ||
244 | return true; | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | |||
249 | return false; | ||
250 | } | ||
113 | } | 251 | } |
114 | 252 | ||
115 | /// <summary> | 253 | /// <summary> |
@@ -157,9 +295,26 @@ namespace OpenSim.Framework.Monitoring | |||
157 | 295 | ||
158 | public virtual double Value { get; set; } | 296 | public virtual double Value { get; set; } |
159 | 297 | ||
298 | /// <summary> | ||
299 | /// Constructor | ||
300 | /// </summary> | ||
301 | /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param> | ||
302 | /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param> | ||
303 | /// <param name='unitName'> | ||
304 | /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value. | ||
305 | /// e.g. " frames" | ||
306 | /// </param> | ||
307 | /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param> | ||
308 | /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param> | ||
309 | /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param> | ||
310 | /// <param name='description'>Description of stat</param> | ||
160 | public Stat( | 311 | public Stat( |
161 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) | 312 | string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description) |
162 | { | 313 | { |
314 | if (StatsManager.SubCommands.Contains(category)) | ||
315 | throw new Exception( | ||
316 | string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); | ||
317 | |||
163 | ShortName = shortName; | 318 | ShortName = shortName; |
164 | Name = name; | 319 | Name = name; |
165 | UnitName = unitName; | 320 | UnitName = unitName; |
@@ -203,7 +358,7 @@ namespace OpenSim.Framework.Monitoring | |||
203 | 358 | ||
204 | public PercentageStat( | 359 | public PercentageStat( |
205 | string shortName, string name, string category, string container, StatVerbosity verbosity, string description) | 360 | string shortName, string name, string category, string container, StatVerbosity verbosity, string description) |
206 | : base(shortName, name, " %", category, container, verbosity, description) | 361 | : base(shortName, name, "%", category, container, verbosity, description) |
207 | { | 362 | { |
208 | } | 363 | } |
209 | } | 364 | } |
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 7a5c16d..aac9c45 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs | |||
@@ -96,11 +96,6 @@ namespace OpenSim.Framework.Servers | |||
96 | get { return m_httpServer; } | 96 | get { return m_httpServer; } |
97 | } | 97 | } |
98 | 98 | ||
99 | /// <summary> | ||
100 | /// Holds the non-viewer statistics collection object for this service/server | ||
101 | /// </summary> | ||
102 | protected IStatsCollector m_stats; | ||
103 | |||
104 | public BaseOpenSimServer() | 99 | public BaseOpenSimServer() |
105 | { | 100 | { |
106 | m_startuptime = DateTime.Now; | 101 | m_startuptime = DateTime.Now; |
@@ -177,10 +172,6 @@ namespace OpenSim.Framework.Servers | |||
177 | "show info", | 172 | "show info", |
178 | "Show general information about the server", HandleShow); | 173 | "Show general information about the server", HandleShow); |
179 | 174 | ||
180 | m_console.Commands.AddCommand("General", false, "show stats", | ||
181 | "show stats", | ||
182 | "Show statistics", HandleShow); | ||
183 | |||
184 | m_console.Commands.AddCommand("General", false, "show threads", | 175 | m_console.Commands.AddCommand("General", false, "show threads", |
185 | "show threads", | 176 | "show threads", |
186 | "Show thread status", HandleShow); | 177 | "Show thread status", HandleShow); |
@@ -226,12 +217,7 @@ namespace OpenSim.Framework.Servers | |||
226 | { | 217 | { |
227 | StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); | 218 | StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); |
228 | sb.Append(GetUptimeReport()); | 219 | sb.Append(GetUptimeReport()); |
229 | 220 | sb.Append(StatsManager.SimExtraStats.Report()); | |
230 | if (m_stats != null) | ||
231 | { | ||
232 | sb.Append(m_stats.Report()); | ||
233 | } | ||
234 | |||
235 | sb.Append(Environment.NewLine); | 221 | sb.Append(Environment.NewLine); |
236 | sb.Append(GetThreadsReport()); | 222 | sb.Append(GetThreadsReport()); |
237 | 223 | ||
@@ -382,10 +368,6 @@ namespace OpenSim.Framework.Servers | |||
382 | { | 368 | { |
383 | Notice("set log level [level] - change the console logging level only. For example, off or debug."); | 369 | Notice("set log level [level] - change the console logging level only. For example, off or debug."); |
384 | Notice("show info - show server information (e.g. startup path)."); | 370 | Notice("show info - show server information (e.g. startup path)."); |
385 | |||
386 | if (m_stats != null) | ||
387 | Notice("show stats - show statistical information for this server"); | ||
388 | |||
389 | Notice("show threads - list tracked threads"); | 371 | Notice("show threads - list tracked threads"); |
390 | Notice("show uptime - show server startup time and uptime."); | 372 | Notice("show uptime - show server startup time and uptime."); |
391 | Notice("show version - show server version."); | 373 | Notice("show version - show server version."); |
@@ -409,11 +391,6 @@ namespace OpenSim.Framework.Servers | |||
409 | ShowInfo(); | 391 | ShowInfo(); |
410 | break; | 392 | break; |
411 | 393 | ||
412 | case "stats": | ||
413 | if (m_stats != null) | ||
414 | Notice(m_stats.Report()); | ||
415 | break; | ||
416 | |||
417 | case "threads": | 394 | case "threads": |
418 | Notice(GetThreadsReport()); | 395 | Notice(GetThreadsReport()); |
419 | break; | 396 | break; |
@@ -604,8 +581,7 @@ namespace OpenSim.Framework.Servers | |||
604 | 581 | ||
605 | public string osSecret { | 582 | public string osSecret { |
606 | // Secret uuid for the simulator | 583 | // Secret uuid for the simulator |
607 | get { return m_osSecret; } | 584 | get { return m_osSecret; } |
608 | |||
609 | } | 585 | } |
610 | 586 | ||
611 | public string StatReport(IOSHttpRequest httpRequest) | 587 | public string StatReport(IOSHttpRequest httpRequest) |
@@ -613,11 +589,11 @@ namespace OpenSim.Framework.Servers | |||
613 | // If we catch a request for "callback", wrap the response in the value for jsonp | 589 | // If we catch a request for "callback", wrap the response in the value for jsonp |
614 | if (httpRequest.Query.ContainsKey("callback")) | 590 | if (httpRequest.Query.ContainsKey("callback")) |
615 | { | 591 | { |
616 | return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; | 592 | return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; |
617 | } | 593 | } |
618 | else | 594 | else |
619 | { | 595 | { |
620 | return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); | 596 | return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); |
621 | } | 597 | } |
622 | } | 598 | } |
623 | 599 | ||
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f784398..4f1b439 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -223,8 +223,6 @@ namespace OpenSim | |||
223 | 223 | ||
224 | base.StartupSpecific(); | 224 | base.StartupSpecific(); |
225 | 225 | ||
226 | m_stats = StatsManager.SimExtraStats; | ||
227 | |||
228 | // Create a ModuleLoader instance | 226 | // Create a ModuleLoader instance |
229 | m_moduleLoader = new ModuleLoader(m_config.Source); | 227 | m_moduleLoader = new ModuleLoader(m_config.Source); |
230 | 228 | ||
@@ -234,51 +232,51 @@ namespace OpenSim | |||
234 | plugin.PostInitialise(); | 232 | plugin.PostInitialise(); |
235 | } | 233 | } |
236 | 234 | ||
237 | AddPluginCommands(); | 235 | if (m_console != null) |
236 | { | ||
237 | StatsManager.RegisterConsoleCommands(m_console); | ||
238 | AddPluginCommands(m_console); | ||
239 | } | ||
238 | } | 240 | } |
239 | 241 | ||
240 | protected virtual void AddPluginCommands() | 242 | protected virtual void AddPluginCommands(CommandConsole console) |
241 | { | 243 | { |
242 | // If console exists add plugin commands. | 244 | List<string> topics = GetHelpTopics(); |
243 | if (m_console != null) | ||
244 | { | ||
245 | List<string> topics = GetHelpTopics(); | ||
246 | 245 | ||
247 | foreach (string topic in topics) | 246 | foreach (string topic in topics) |
248 | { | 247 | { |
249 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); | 248 | string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); |
250 | 249 | ||
251 | // This is a hack to allow the user to enter the help command in upper or lowercase. This will go | 250 | // This is a hack to allow the user to enter the help command in upper or lowercase. This will go |
252 | // away at some point. | 251 | // away at some point. |
253 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, | 252 | console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, |
254 | "help " + capitalizedTopic, | 253 | "help " + capitalizedTopic, |
255 | "Get help on plugin command '" + topic + "'", | 254 | "Get help on plugin command '" + topic + "'", |
256 | HandleCommanderHelp); | 255 | HandleCommanderHelp); |
257 | m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, | 256 | console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, |
258 | "help " + capitalizedTopic, | 257 | "help " + capitalizedTopic, |
259 | "Get help on plugin command '" + topic + "'", | 258 | "Get help on plugin command '" + topic + "'", |
260 | HandleCommanderHelp); | 259 | HandleCommanderHelp); |
261 | 260 | ||
262 | ICommander commander = null; | 261 | ICommander commander = null; |
263 | 262 | ||
264 | Scene s = SceneManager.CurrentOrFirstScene; | 263 | Scene s = SceneManager.CurrentOrFirstScene; |
265 | 264 | ||
266 | if (s != null && s.GetCommanders() != null) | 265 | if (s != null && s.GetCommanders() != null) |
267 | { | 266 | { |
268 | if (s.GetCommanders().ContainsKey(topic)) | 267 | if (s.GetCommanders().ContainsKey(topic)) |
269 | commander = s.GetCommanders()[topic]; | 268 | commander = s.GetCommanders()[topic]; |
270 | } | 269 | } |
271 | 270 | ||
272 | if (commander == null) | 271 | if (commander == null) |
273 | continue; | 272 | continue; |
274 | 273 | ||
275 | foreach (string command in commander.Commands.Keys) | 274 | foreach (string command in commander.Commands.Keys) |
276 | { | 275 | { |
277 | m_console.Commands.AddCommand(capitalizedTopic, false, | 276 | console.Commands.AddCommand(capitalizedTopic, false, |
278 | topic + " " + command, | 277 | topic + " " + command, |
279 | topic + " " + commander.Commands[command].ShortHelp(), | 278 | topic + " " + commander.Commands[command].ShortHelp(), |
280 | String.Empty, HandleCommanderCommand); | 279 | String.Empty, HandleCommanderCommand); |
281 | } | ||
282 | } | 280 | } |
283 | } | 281 | } |
284 | } | 282 | } |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs index fc9406b..3d9f94f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs | |||
@@ -31,6 +31,7 @@ using System.Reflection; | |||
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenMetaverse.Packets; | 32 | using OpenMetaverse.Packets; |
33 | using log4net; | 33 | using log4net; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | 35 | ||
35 | namespace OpenSim.Region.ClientStack.LindenUDP | 36 | namespace OpenSim.Region.ClientStack.LindenUDP |
36 | { | 37 | { |
@@ -43,17 +44,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
43 | private bool packetPoolEnabled = true; | 44 | private bool packetPoolEnabled = true; |
44 | private bool dataBlockPoolEnabled = true; | 45 | private bool dataBlockPoolEnabled = true; |
45 | 46 | ||
47 | private PercentageStat m_packetsReusedStat = new PercentageStat( | ||
48 | "PacketsReused", | ||
49 | "Packets reused", | ||
50 | "simulator", | ||
51 | "simulator", | ||
52 | StatVerbosity.Debug, | ||
53 | "Number of packets reused out of all requests to the packet pool"); | ||
54 | |||
55 | private PercentageStat m_blocksReusedStat = new PercentageStat( | ||
56 | "BlocksReused", | ||
57 | "Blocks reused", | ||
58 | "simulator", | ||
59 | "simulator", | ||
60 | StatVerbosity.Debug, | ||
61 | "Number of data blocks reused out of all requests to the packet pool"); | ||
62 | |||
46 | /// <summary> | 63 | /// <summary> |
47 | /// Pool of packets available for reuse. | 64 | /// Pool of packets available for reuse. |
48 | /// </summary> | 65 | /// </summary> |
49 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); | 66 | private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); |
50 | 67 | ||
51 | private static Dictionary<Type, Stack<Object>> DataBlocks = | 68 | private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); |
52 | new Dictionary<Type, Stack<Object>>(); | ||
53 | |||
54 | static PacketPool() | ||
55 | { | ||
56 | } | ||
57 | 69 | ||
58 | public static PacketPool Instance | 70 | public static PacketPool Instance |
59 | { | 71 | { |
@@ -72,8 +84,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
72 | get { return dataBlockPoolEnabled; } | 84 | get { return dataBlockPoolEnabled; } |
73 | } | 85 | } |
74 | 86 | ||
87 | private PacketPool() | ||
88 | { | ||
89 | StatsManager.RegisterStat(m_packetsReusedStat); | ||
90 | StatsManager.RegisterStat(m_blocksReusedStat); | ||
91 | } | ||
92 | |||
75 | public Packet GetPacket(PacketType type) | 93 | public Packet GetPacket(PacketType type) |
76 | { | 94 | { |
95 | m_packetsReusedStat.Consequent++; | ||
96 | |||
77 | Packet packet; | 97 | Packet packet; |
78 | 98 | ||
79 | if (!packetPoolEnabled) | 99 | if (!packetPoolEnabled) |
@@ -89,6 +109,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
89 | else | 109 | else |
90 | { | 110 | { |
91 | // Recycle old packages | 111 | // Recycle old packages |
112 | m_packetsReusedStat.Antecedent++; | ||
113 | |||
92 | packet = (pool[type]).Pop(); | 114 | packet = (pool[type]).Pop(); |
93 | } | 115 | } |
94 | } | 116 | } |
@@ -211,16 +233,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
211 | } | 233 | } |
212 | } | 234 | } |
213 | 235 | ||
214 | public static T GetDataBlock<T>() where T: new() | 236 | public T GetDataBlock<T>() where T: new() |
215 | { | 237 | { |
216 | lock (DataBlocks) | 238 | lock (DataBlocks) |
217 | { | 239 | { |
240 | m_blocksReusedStat.Consequent++; | ||
241 | |||
218 | Stack<Object> s; | 242 | Stack<Object> s; |
219 | 243 | ||
220 | if (DataBlocks.TryGetValue(typeof(T), out s)) | 244 | if (DataBlocks.TryGetValue(typeof(T), out s)) |
221 | { | 245 | { |
222 | if (s.Count > 0) | 246 | if (s.Count > 0) |
247 | { | ||
248 | m_blocksReusedStat.Antecedent++; | ||
223 | return (T)s.Pop(); | 249 | return (T)s.Pop(); |
250 | } | ||
224 | } | 251 | } |
225 | else | 252 | else |
226 | { | 253 | { |
@@ -231,7 +258,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
231 | } | 258 | } |
232 | } | 259 | } |
233 | 260 | ||
234 | public static void ReturnDataBlock<T>(T block) where T: new() | 261 | public void ReturnDataBlock<T>(T block) where T: new() |
235 | { | 262 | { |
236 | if (block == null) | 263 | if (block == null) |
237 | return; | 264 | return; |