diff options
author | Justin Clark-Casey (justincc) | 2013-08-01 21:16:53 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2013-08-01 21:16:53 +0100 |
commit | 216e785ca9ca7dee51c32e69952a79b6e87733d1 (patch) | |
tree | 23b0c79da034868d12c4b7dfd15ee4051f9fba04 /OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |
parent | Try a different approach to slow terrain update by always cycling the loop im... (diff) | |
download | opensim-SC_OLD-216e785ca9ca7dee51c32e69952a79b6e87733d1.zip opensim-SC_OLD-216e785ca9ca7dee51c32e69952a79b6e87733d1.tar.gz opensim-SC_OLD-216e785ca9ca7dee51c32e69952a79b6e87733d1.tar.bz2 opensim-SC_OLD-216e785ca9ca7dee51c32e69952a79b6e87733d1.tar.xz |
Add experimental "debug attachments throttle <ms>" setting (command line) and ThrottlePer100PrimsRezzed in [Attachments] in config
This is an experimental setting to control cpu spikes when an attachment heavy avatar logs in or avatars with medium attachments lgoin simultaneously.
It inserts a ms sleep specified in terms of attachments prims after each rez when an avatar logs in.
Default is 0 (no throttling).
"debug attachments <level>" changes to "debug attachments log <level>" which controls logging. A logging level of 1 will show the throttling performed if applicable.
Also adds "debug attachments status" command to show current throttle and debug logging levels.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 102 |
1 files changed, 87 insertions, 15 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 2f5a76f..97477d4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Threading; | ||
32 | using System.Xml; | 33 | using System.Xml; |
33 | using log4net; | 34 | using log4net; |
34 | using Mono.Addins; | 35 | using Mono.Addins; |
@@ -50,6 +51,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 51 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | 52 | ||
52 | public int DebugLevel { get; set; } | 53 | public int DebugLevel { get; set; } |
54 | |||
55 | /// <summary> | ||
56 | /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in | ||
57 | /// or many avatars with a medium levels of attachments login simultaneously. | ||
58 | /// </summary> | ||
59 | /// <remarks> | ||
60 | /// A value of 0 will apply no pause. The pause is specified in milliseconds. | ||
61 | /// </remarks> | ||
62 | public int ThrottlePer100PrimsRezzed { get; set; } | ||
53 | 63 | ||
54 | private Scene m_scene; | 64 | private Scene m_scene; |
55 | private IInventoryAccessModule m_invAccessModule; | 65 | private IInventoryAccessModule m_invAccessModule; |
@@ -66,9 +76,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
66 | { | 76 | { |
67 | IConfig config = source.Configs["Attachments"]; | 77 | IConfig config = source.Configs["Attachments"]; |
68 | if (config != null) | 78 | if (config != null) |
79 | { | ||
69 | Enabled = config.GetBoolean("Enabled", true); | 80 | Enabled = config.GetBoolean("Enabled", true); |
81 | |||
82 | ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0); | ||
83 | } | ||
70 | else | 84 | else |
85 | { | ||
71 | Enabled = true; | 86 | Enabled = true; |
87 | } | ||
72 | } | 88 | } |
73 | 89 | ||
74 | public void AddRegion(Scene scene) | 90 | public void AddRegion(Scene scene) |
@@ -87,24 +103,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
87 | MainConsole.Instance.Commands.AddCommand( | 103 | MainConsole.Instance.Commands.AddCommand( |
88 | "Debug", | 104 | "Debug", |
89 | false, | 105 | false, |
90 | "debug attachments", | 106 | "debug attachments log", |
91 | "debug attachments [0|1]", | 107 | "debug attachments log [0|1]", |
92 | "Turn on attachments debugging\n" | 108 | "Turn on attachments debug logging", |
93 | + " <= 0 - turns off debugging\n" | 109 | " <= 0 - turns off debug logging\n" |
94 | + " >= 1 - turns on attachment message logging\n", | 110 | + " >= 1 - turns on attachment message debug logging", |
95 | HandleDebugAttachments); | 111 | HandleDebugAttachmentsLog); |
112 | |||
113 | MainConsole.Instance.Commands.AddCommand( | ||
114 | "Debug", | ||
115 | false, | ||
116 | "debug attachments throttle", | ||
117 | "debug attachments throttle <ms>", | ||
118 | "Turn on attachments throttling.", | ||
119 | "This requires a millisecond value. " + | ||
120 | " == 0 - disable throttling.\n" | ||
121 | + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.", | ||
122 | HandleDebugAttachmentsThrottle); | ||
123 | |||
124 | MainConsole.Instance.Commands.AddCommand( | ||
125 | "Debug", | ||
126 | false, | ||
127 | "debug attachments status", | ||
128 | "debug attachments status", | ||
129 | "Show current attachments debug status", | ||
130 | HandleDebugAttachmentsStatus); | ||
96 | } | 131 | } |
97 | 132 | ||
98 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI | 133 | // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI |
99 | } | 134 | } |
100 | 135 | ||
101 | private void HandleDebugAttachments(string module, string[] args) | 136 | private void HandleDebugAttachmentsLog(string module, string[] args) |
102 | { | 137 | { |
103 | int debugLevel; | 138 | int debugLevel; |
104 | 139 | ||
105 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | 140 | if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel))) |
106 | { | 141 | { |
107 | MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); | 142 | MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]"); |
108 | } | 143 | } |
109 | else | 144 | else |
110 | { | 145 | { |
@@ -114,6 +149,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
114 | } | 149 | } |
115 | } | 150 | } |
116 | 151 | ||
152 | private void HandleDebugAttachmentsThrottle(string module, string[] args) | ||
153 | { | ||
154 | int ms; | ||
155 | |||
156 | if (args.Length == 4 && int.TryParse(args[3], out ms)) | ||
157 | { | ||
158 | ThrottlePer100PrimsRezzed = ms; | ||
159 | MainConsole.Instance.OutputFormat( | ||
160 | "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name); | ||
161 | |||
162 | return; | ||
163 | } | ||
164 | |||
165 | MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>"); | ||
166 | } | ||
167 | |||
168 | private void HandleDebugAttachmentsStatus(string module, string[] args) | ||
169 | { | ||
170 | MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name); | ||
171 | MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel); | ||
172 | MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed); | ||
173 | } | ||
174 | |||
117 | /// <summary> | 175 | /// <summary> |
118 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. | 176 | /// Listen for client triggered running state changes so that we can persist the script's object if necessary. |
119 | /// </summary> | 177 | /// </summary> |
@@ -240,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
240 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); | 298 | List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); |
241 | foreach (AvatarAttachment attach in attachments) | 299 | foreach (AvatarAttachment attach in attachments) |
242 | { | 300 | { |
243 | uint p = (uint)attach.AttachPoint; | 301 | uint attachmentPt = (uint)attach.AttachPoint; |
244 | 302 | ||
245 | // m_log.DebugFormat( | 303 | // m_log.DebugFormat( |
246 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", | 304 | // "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", |
@@ -258,14 +316,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
258 | { | 316 | { |
259 | // If we're an NPC then skip all the item checks and manipulations since we don't have an | 317 | // If we're an NPC then skip all the item checks and manipulations since we don't have an |
260 | // inventory right now. | 318 | // inventory right now. |
261 | RezSingleAttachmentFromInventoryInternal( | 319 | SceneObjectGroup objatt |
262 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true); | 320 | = RezSingleAttachmentFromInventoryInternal( |
321 | sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true); | ||
322 | |||
323 | |||
324 | if (ThrottlePer100PrimsRezzed > 0) | ||
325 | { | ||
326 | int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed); | ||
327 | |||
328 | if (DebugLevel > 0) | ||
329 | m_log.DebugFormat( | ||
330 | "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}", | ||
331 | throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); | ||
332 | |||
333 | Thread.Sleep(throttleMs); | ||
334 | } | ||
263 | } | 335 | } |
264 | catch (Exception e) | 336 | catch (Exception e) |
265 | { | 337 | { |
266 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; | 338 | UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; |
267 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", | 339 | m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", |
268 | attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); | 340 | attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace); |
269 | } | 341 | } |
270 | } | 342 | } |
271 | } | 343 | } |
@@ -919,8 +991,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
919 | 991 | ||
920 | if (DebugLevel > 0) | 992 | if (DebugLevel > 0) |
921 | m_log.DebugFormat( | 993 | m_log.DebugFormat( |
922 | "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", | 994 | "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}", |
923 | objatt.Name, sp.Name, attachmentPt, m_scene.Name); | 995 | objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name); |
924 | 996 | ||
925 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 997 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
926 | objatt.HasGroupChanged = false; | 998 | objatt.HasGroupChanged = false; |