aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorMelanie2012-04-13 03:00:48 +0100
committerMelanie2012-04-13 03:00:48 +0100
commitfe65b518765a8c88c1f3067b47d775b9b1142961 (patch)
tree3a97f13715090d8c925543ae49ecae1930578d5d
parentMerge branch 'master' into careminster (diff)
parentMantis 55025 Implement script time. (diff)
downloadopensim-SC-fe65b518765a8c88c1f3067b47d775b9b1142961.zip
opensim-SC-fe65b518765a8c88c1f3067b47d775b9b1142961.tar.gz
opensim-SC-fe65b518765a8c88c1f3067b47d775b9b1142961.tar.bz2
opensim-SC-fe65b518765a8c88c1f3067b47d775b9b1142961.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs116
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs82
-rw-r--r--bin/config-include/FlotsamCache.ini.example4
8 files changed, 178 insertions, 109 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 4d70888..8732ec0 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -174,7 +174,17 @@ namespace OpenSim.Region.Framework.Interfaces
174 /// If no inventory item has that name then an empty list is returned. 174 /// If no inventory item has that name then an empty list is returned.
175 /// </returns> 175 /// </returns>
176 List<TaskInventoryItem> GetInventoryItems(string name); 176 List<TaskInventoryItem> GetInventoryItems(string name);
177 177
178 /// <summary>
179 /// Get inventory items by type.
180 /// </summary>
181 /// <param type="name"></param>
182 /// <returns>
183 /// A list of inventory items of that type.
184 /// If no inventory items of that type then an empty list is returned.
185 /// </returns>
186 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
187
178 /// <summary> 188 /// <summary>
179 /// Get the scene object referenced by an inventory item. 189 /// Get the scene object referenced by an inventory item.
180 /// </summary> 190 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 4f8be10..143af48 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -85,6 +85,14 @@ namespace OpenSim.Region.Framework.Interfaces
85 void StartProcessing(); 85 void StartProcessing();
86 86
87 /// <summary> 87 /// <summary>
88 /// Get the execution times of all scripts in the given array if they are currently running.
89 /// </summary>
90 /// <returns>
91 /// A float the value is a representative execution time in milliseconds of all scripts in that Array.
92 /// </returns>
93 float GetScriptExecutionTime(List<UUID> itemIDs);
94
95 /// <summary>
88 /// Get the execution times of all scripts in each object. 96 /// Get the execution times of all scripts in each object.
89 /// </summary> 97 /// </summary>
90 /// <returns> 98 /// <returns>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 5786f48..ced3fb5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -4032,6 +4032,45 @@ namespace OpenSim.Region.Framework.Scenes
4032 } 4032 }
4033 4033
4034 /// <summary> 4034 /// <summary>
4035 /// A float the value is a representative execution time in milliseconds of all scripts in the link set.
4036 /// </summary>
4037 public float ScriptExecutionTime()
4038 {
4039 IScriptModule[] engines = Scene.RequestModuleInterfaces<IScriptModule>();
4040
4041 if (engines.Length == 0) // No engine at all
4042 return 0.0f;
4043
4044 float time = 0.0f;
4045
4046 // get all the scripts in all parts
4047 SceneObjectPart[] parts = m_parts.GetArray();
4048 List<TaskInventoryItem> scripts = new List<TaskInventoryItem>();
4049 for (int i = 0; i < parts.Length; i++)
4050 {
4051 scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL));
4052 }
4053 // extract the UUIDs
4054 List<UUID> ids = new List<UUID>(scripts.Count);
4055 foreach (TaskInventoryItem script in scripts)
4056 {
4057 if (!ids.Contains(script.ItemID))
4058 {
4059 ids.Add(script.ItemID);
4060 }
4061 }
4062 // Offer the list of script UUIDs to each engine found and accumulate the time
4063 foreach (IScriptModule e in engines)
4064 {
4065 if (e != null)
4066 {
4067 time += e.GetScriptExecutionTime(ids);
4068 }
4069 }
4070 return time;
4071 }
4072
4073 /// <summary>
4035 /// Returns a count of the number of running scripts in this groups parts. 4074 /// Returns a count of the number of running scripts in this groups parts.
4036 /// </summary> 4075 /// </summary>
4037 public int RunningScriptCount() 4076 public int RunningScriptCount()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 7e629c0..36cb09a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -267,14 +267,9 @@ namespace OpenSim.Region.Framework.Scenes
267 /// </summary> 267 /// </summary>
268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
269 { 269 {
270 Items.LockItemsForRead(true); 270 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 271 foreach (TaskInventoryItem item in scripts)
272 Items.LockItemsForRead(false); 272 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
278 } 273 }
279 274
280 public ArrayList GetScriptErrors(UUID itemID) 275 public ArrayList GetScriptErrors(UUID itemID)
@@ -305,17 +300,11 @@ namespace OpenSim.Region.Framework.Scenes
305 /// </param> 300 /// </param>
306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 301 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
307 { 302 {
308 Items.LockItemsForRead(true); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 304 foreach (TaskInventoryItem item in scripts)
310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 { 305 {
314 if ((int)InventoryType.LSL == item.InvType) 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
315 { 307 m_part.RemoveScriptEvents(item.ItemID);
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 } 308 }
320 } 309 }
321 310
@@ -1291,17 +1280,15 @@ namespace OpenSim.Region.Framework.Scenes
1291 public int ScriptCount() 1280 public int ScriptCount()
1292 { 1281 {
1293 int count = 0; 1282 int count = 0;
1294 lock (m_items) 1283 Items.LockItemsForRead(true);
1284 foreach (TaskInventoryItem item in m_items.Values)
1295 { 1285 {
1296 foreach (TaskInventoryItem item in m_items.Values) 1286 if (item.InvType == (int)InventoryType.LSL)
1297 { 1287 {
1298 if (item.InvType == (int)InventoryType.LSL) 1288 count++;
1299 {
1300 count++;
1301 }
1302 } 1289 }
1303 } 1290 }
1304 1291 Items.LockItemsForRead(false);
1305 return count; 1292 return count;
1306 } 1293 }
1307 /// <summary> 1294 /// <summary>
@@ -1315,7 +1302,7 @@ namespace OpenSim.Region.Framework.Scenes
1315 return 0; 1302 return 0;
1316 1303
1317 int count = 0; 1304 int count = 0;
1318 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1305 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1319 1306
1320 foreach (TaskInventoryItem item in scripts) 1307 foreach (TaskInventoryItem item in scripts)
1321 { 1308 {
@@ -1347,22 +1334,24 @@ namespace OpenSim.Region.Framework.Scenes
1347 { 1334 {
1348 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1335 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1349 1336
1350 lock (m_items) 1337 Items.LockItemsForRead(true);
1351 ret = new List<TaskInventoryItem>(m_items.Values); 1338 ret = new List<TaskInventoryItem>(m_items.Values);
1339 Items.LockItemsForRead(false);
1352 1340
1353 return ret; 1341 return ret;
1354 } 1342 }
1355 1343
1356 public List<TaskInventoryItem> GetInventoryScripts() 1344 public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
1357 { 1345 {
1358 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1346 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1359 1347
1360 lock (m_items) 1348 Items.LockItemsForRead(true);
1361 { 1349
1362 foreach (TaskInventoryItem item in m_items.Values) 1350 foreach (TaskInventoryItem item in m_items.Values)
1363 if (item.InvType == (int)InventoryType.LSL) 1351 if (item.InvType == (int)type)
1364 ret.Add(item); 1352 ret.Add(item);
1365 } 1353
1354 Items.LockItemsForRead(false);
1366 1355
1367 return ret; 1356 return ret;
1368 } 1357 }
@@ -1384,35 +1373,32 @@ namespace OpenSim.Region.Framework.Scenes
1384 if (engines.Length == 0) // No engine at all 1373 if (engines.Length == 0) // No engine at all
1385 return ret; 1374 return ret;
1386 1375
1387 Items.LockItemsForRead(true); 1376 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1388 foreach (TaskInventoryItem item in m_items.Values) 1377
1378 foreach (TaskInventoryItem item in scripts)
1389 { 1379 {
1390 if (item.InvType == (int)InventoryType.LSL) 1380 foreach (IScriptModule e in engines)
1391 { 1381 {
1392 foreach (IScriptModule e in engines) 1382 if (e != null)
1393 { 1383 {
1394 if (e != null) 1384 string n = e.GetXMLState(item.ItemID);
1385 if (n != String.Empty)
1395 { 1386 {
1396 string n = e.GetXMLState(item.ItemID); 1387 if (oldIDs)
1397 if (n != String.Empty) 1388 {
1389 if (!ret.ContainsKey(item.OldItemID))
1390 ret[item.OldItemID] = n;
1391 }
1392 else
1398 { 1393 {
1399 if (oldIDs) 1394 if (!ret.ContainsKey(item.ItemID))
1400 { 1395 ret[item.ItemID] = n;
1401 if (!ret.ContainsKey(item.OldItemID))
1402 ret[item.OldItemID] = n;
1403 }
1404 else
1405 {
1406 if (!ret.ContainsKey(item.ItemID))
1407 ret[item.ItemID] = n;
1408 }
1409 break;
1410 } 1396 }
1397 break;
1411 } 1398 }
1412 } 1399 }
1413 } 1400 }
1414 } 1401 }
1415 Items.LockItemsForRead(false);
1416 return ret; 1402 return ret;
1417 } 1403 }
1418 1404
@@ -1422,27 +1408,21 @@ namespace OpenSim.Region.Framework.Scenes
1422 if (engines.Length == 0) 1408 if (engines.Length == 0)
1423 return; 1409 return;
1424 1410
1411 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
1425 1412
1426 Items.LockItemsForRead(true); 1413 foreach (TaskInventoryItem item in scripts)
1427
1428 foreach (TaskInventoryItem item in m_items.Values)
1429 { 1414 {
1430 if (item.InvType == (int)InventoryType.LSL) 1415 foreach (IScriptModule engine in engines)
1431 { 1416 {
1432 foreach (IScriptModule engine in engines) 1417 if (engine != null)
1433 { 1418 {
1434 if (engine != null) 1419 if (item.OwnerChanged)
1435 { 1420 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1436 if (item.OwnerChanged) 1421 item.OwnerChanged = false;
1437 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1422 engine.ResumeScript(item.ItemID);
1438 item.OwnerChanged = false;
1439 engine.ResumeScript(item.ItemID);
1440 }
1441 } 1423 }
1442 } 1424 }
1443 } 1425 }
1444
1445 Items.LockItemsForRead(false);
1446 } 1426 }
1447 } 1427 }
1448} 1428}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 0cb1556..fd7f7d8 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3541,6 +3541,25 @@ namespace OpenSim.Region.Framework.Scenes
3541 } 3541 }
3542 3542
3543 /// <summary> 3543 /// <summary>
3544 /// A float the value is a representative execution time in milliseconds of all scripts in all attachments.
3545 /// </summary>
3546 public float ScriptExecutionTime()
3547 {
3548 float time = 0.0f;
3549 lock (m_attachments)
3550 {
3551 foreach (SceneObjectGroup gobj in m_attachments)
3552 {
3553 if (gobj != null)
3554 {
3555 time += gobj.ScriptExecutionTime();
3556 }
3557 }
3558 }
3559 return time;
3560 }
3561
3562 /// <summary>
3544 /// Returns the total count of running scripts in all parts. 3563 /// Returns the total count of running scripts in all parts.
3545 /// </summary> 3564 /// </summary>
3546 public int RunningScriptCount() 3565 public int RunningScriptCount()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 76106a0..783650c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -11176,7 +11176,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11176 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384)); 11176 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384));
11177 break; 11177 break;
11178 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11178 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
11179 ret.Add(new LSL_Float(0)); 11179 ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f));
11180 break; 11180 break;
11181 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11181 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
11182 ret.Add(new LSL_Integer(1)); 11182 ret.Add(new LSL_Integer(1));
@@ -11244,9 +11244,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11244 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384)); 11244 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384));
11245 break; 11245 break;
11246 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 11246 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
11247 // Average cpu time per simulator frame expended on all scripts in the object 11247 // Average cpu time in seconds per simulator frame expended on all scripts in the object
11248 // Not currently available at Object level 11248 ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f));
11249 ret.Add(new LSL_Float(0));
11250 break; 11249 break;
11251 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 11250 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
11252 // according to the SL wiki A prim or linkset will have prim 11251 // according to the SL wiki A prim or linkset will have prim
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 1e0f01f..bfe7418 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -1997,45 +1997,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1997 if (!topScripts.ContainsKey(si.LocalID)) 1997 if (!topScripts.ContainsKey(si.LocalID))
1998 topScripts[si.RootLocalID] = 0; 1998 topScripts[si.RootLocalID] = 0;
1999 1999
2000// long ticksElapsed = tickNow - si.MeasurementPeriodTickStart; 2000 topScripts[si.RootLocalID] += CalculateAdjustedExectionTime(si, tickNow);
2001// float framesElapsed = ticksElapsed / (18.1818 * TimeSpan.TicksPerMillisecond); 2001 }
2002 2002 }
2003 // Execution time of the script adjusted by it's measurement period to make scripts started at
2004 // different times comparable.
2005// float adjustedExecutionTime
2006// = (float)si.MeasurementPeriodExecutionTime
2007// / ((float)(tickNow - si.MeasurementPeriodTickStart) / ScriptInstance.MaxMeasurementPeriod)
2008// / TimeSpan.TicksPerMillisecond;
2009
2010 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2011
2012 // Avoid divide by zerp
2013 if (ticksElapsed == 0)
2014 ticksElapsed = 1;
2015 2003
2016 // Scale execution time to the ideal 55 fps frame time for these reasons. 2004 return topScripts;
2017 // 2005 }
2018 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2019 // 'script execution time per frame', which is the original purpose of this value.
2020 //
2021 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2022 // it impossible to compare scripts.
2023 //
2024 // 3) Scaling the raw execution time to the time that the script has been running is better but
2025 // is still misleading since a script that has just been rezzed may appear to have been running
2026 // for much longer.
2027 //
2028 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2029 // since the figure does not represent actual execution time and very hard running scripts will
2030 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2031 float adjustedExecutionTime
2032 = ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2033 2006
2034 topScripts[si.RootLocalID] += adjustedExecutionTime; 2007 public float GetScriptExecutionTime(List<UUID> itemIDs)
2008 {
2009 if (itemIDs == null|| itemIDs.Count == 0)
2010 {
2011 return 0.0f;
2012 }
2013 float time = 0.0f;
2014 long tickNow = Util.EnvironmentTickCount();
2015 IScriptInstance si;
2016 // Calculate the time for all scripts that this engine is executing
2017 // Ignore any others
2018 foreach (UUID id in itemIDs)
2019 {
2020 si = GetInstance(id);
2021 if (si != null && si.Running)
2022 {
2023 time += CalculateAdjustedExectionTime(si, tickNow);
2035 } 2024 }
2036 } 2025 }
2026 return time;
2027 }
2037 2028
2038 return topScripts; 2029 private float CalculateAdjustedExectionTime(IScriptInstance si, long tickNow)
2030 {
2031 long ticksElapsed = tickNow - si.MeasurementPeriodTickStart;
2032
2033 // Avoid divide by zero
2034 if (ticksElapsed == 0)
2035 ticksElapsed = 1;
2036
2037 // Scale execution time to the ideal 55 fps frame time for these reasons.
2038 //
2039 // 1) XEngine does not execute scripts per frame, unlike other script engines. Hence, there is no
2040 // 'script execution time per frame', which is the original purpose of this value.
2041 //
2042 // 2) Giving the raw execution times is misleading since scripts start at different times, making
2043 // it impossible to compare scripts.
2044 //
2045 // 3) Scaling the raw execution time to the time that the script has been running is better but
2046 // is still misleading since a script that has just been rezzed may appear to have been running
2047 // for much longer.
2048 //
2049 // 4) Hence, we scale execution time to an idealised frame time (55 fps). This is also not perfect
2050 // since the figure does not represent actual execution time and very hard running scripts will
2051 // never exceed 18ms (though this is a very high number for script execution so is a warning sign).
2052 return ((float)si.MeasurementPeriodExecutionTime / ticksElapsed) * 18.1818f;
2039 } 2053 }
2040 2054
2041 public void SuspendScript(UUID itemID) 2055 public void SuspendScript(UUID itemID)
diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example
index cd39f8c..b9c6d84 100644
--- a/bin/config-include/FlotsamCache.ini.example
+++ b/bin/config-include/FlotsamCache.ini.example
@@ -36,7 +36,7 @@
36 36
37 ; How often {in hours} should the disk be checked for expired filed 37 ; How often {in hours} should the disk be checked for expired filed
38 ; Specify 0 to disable expiration checking 38 ; Specify 0 to disable expiration checking
39 FileCleanupTimer = .166 ;roughly every 10 minutes 39 FileCleanupTimer = 1.0 ;every hour
40 40
41 ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how 41 ; If WAIT_ON_INPROGRESS_REQUESTS has been defined then this specifies how
42 ; long (in miliseconds) to block a request thread while trying to complete 42 ; long (in miliseconds) to block a request thread while trying to complete
@@ -60,4 +60,4 @@
60 ; cache, and request all assets that are found that are not already cached (this 60 ; cache, and request all assets that are found that are not already cached (this
61 ; will cause those assets to be cached) 61 ; will cause those assets to be cached)
62 ; 62 ;
63 ; DeepScanBeforePurge = false 63 DeepScanBeforePurge = true