add mrieker fresh optimization on heap tracker

httptests
UbitUmarov 2018-02-05 12:48:07 +00:00
parent a7e2978db9
commit 38cd12b3cf
5 changed files with 155 additions and 66 deletions

View File

@ -141,9 +141,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
new Type[] { typeof (LSL_Vector) }); new Type[] { typeof (LSL_Vector) });
private static MethodInfo scriptRestoreCatchExceptionUnwrap = GetStaticMethod (typeof (ScriptRestoreCatchException), "Unwrap", new Type[] { typeof (Exception) }); private static MethodInfo scriptRestoreCatchExceptionUnwrap = GetStaticMethod (typeof (ScriptRestoreCatchException), "Unwrap", new Type[] { typeof (Exception) });
private static MethodInfo thrownExceptionWrapMethodInfo = GetStaticMethod (typeof (ScriptThrownException), "Wrap", new Type[] { typeof (object) }); private static MethodInfo thrownExceptionWrapMethodInfo = GetStaticMethod (typeof (ScriptThrownException), "Wrap", new Type[] { typeof (object) });
private static MethodInfo heapTrackerListPush = typeof (HeapTrackerList). GetMethod ("Push", new Type[0]);
private static MethodInfo heapTrackerObjectPush = typeof (HeapTrackerObject).GetMethod ("Push", new Type[0]);
private static MethodInfo heapTrackerStringPush = typeof (HeapTrackerString).GetMethod ("Push", new Type[0]);
private static MethodInfo catchExcToStrMethodInfo = GetStaticMethod (typeof (ScriptCodeGen), private static MethodInfo catchExcToStrMethodInfo = GetStaticMethod (typeof (ScriptCodeGen),
"CatchExcToStr", "CatchExcToStr",
@ -1510,16 +1507,13 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
ilGen.Emit (curDeclFunc, OpCodes.Ldloc, lcl); ilGen.Emit (curDeclFunc, OpCodes.Ldloc, lcl);
Type t = lcl.type; Type t = lcl.type;
if (t == typeof (HeapTrackerList)) { if (t == typeof (HeapTrackerList)) {
ilGen.Emit (curDeclFunc, OpCodes.Call, heapTrackerListPush); t = HeapTrackerList.GenPush (curDeclFunc, ilGen);
t = typeof (LSL_List);
} }
if (t == typeof (HeapTrackerObject)) { if (t == typeof (HeapTrackerObject)) {
ilGen.Emit (curDeclFunc, OpCodes.Call, heapTrackerObjectPush); t = HeapTrackerObject.GenPush (curDeclFunc, ilGen);
t = typeof (object);
} }
if (t == typeof (HeapTrackerString)) { if (t == typeof(HeapTrackerString)) {
ilGen.Emit (curDeclFunc, OpCodes.Call, heapTrackerStringPush); t = HeapTrackerString.GenPush (curDeclFunc, ilGen);
t = typeof (string);
} }
if (t.IsValueType) { if (t.IsValueType) {
ilGen.Emit (curDeclFunc, OpCodes.Box, t); ilGen.Emit (curDeclFunc, OpCodes.Box, t);
@ -1615,7 +1609,9 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
ilGen.Emit (curDeclFunc, OpCodes.Castclass, u); ilGen.Emit (curDeclFunc, OpCodes.Castclass, u);
} }
if (u != t) { if (u != t) {
ilGen.Emit (curDeclFunc, OpCodes.Call, t.GetMethod ("Pop", new Type[] { u })); if (t == typeof (HeapTrackerList)) HeapTrackerList.GenPop (curDeclFunc, ilGen);
if (t == typeof (HeapTrackerObject)) HeapTrackerObject.GenPop (curDeclFunc, ilGen);
if (t == typeof (HeapTrackerString)) HeapTrackerString.GenPop (curDeclFunc, ilGen);
} else { } else {
ilGen.Emit (curDeclFunc, OpCodes.Stloc, lcl); ilGen.Emit (curDeclFunc, OpCodes.Stloc, lcl);
} }

View File

@ -1313,7 +1313,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
{ {
scg.ilGen.Emit (errorAt, OpCodes.Ldloc, localBuilder); scg.ilGen.Emit (errorAt, OpCodes.Ldloc, localBuilder);
if (type.ToHeapTrackerType () != null) { if (type.ToHeapTrackerType () != null) {
scg.ilGen.Emit (errorAt, OpCodes.Call, type.GetHeapTrackerPushMeth ()); type.CallHeapTrackerPushMeth (errorAt, scg.ilGen);
} }
} }
public override void PushRef (ScriptCodeGen scg, Token errorAt) public override void PushRef (ScriptCodeGen scg, Token errorAt)
@ -1335,7 +1335,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
public override void PopPost (ScriptCodeGen scg, Token errorAt) public override void PopPost (ScriptCodeGen scg, Token errorAt)
{ {
if (type.ToHeapTrackerType () != null) { if (type.ToHeapTrackerType () != null) {
scg.ilGen.Emit (errorAt, OpCodes.Call, type.GetHeapTrackerPopMeth ()); type.CallHeapTrackerPopMeth (errorAt, scg.ilGen);
} else { } else {
scg.ilGen.Emit (errorAt, OpCodes.Stloc, localBuilder); scg.ilGen.Emit (errorAt, OpCodes.Stloc, localBuilder);
} }
@ -1352,7 +1352,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
scg.ilGen.Emit (errorAt, OpCodes.Stloc, htpop); scg.ilGen.Emit (errorAt, OpCodes.Stloc, htpop);
scg.ilGen.Emit (errorAt, OpCodes.Ldloc, localBuilder); scg.ilGen.Emit (errorAt, OpCodes.Ldloc, localBuilder);
scg.ilGen.Emit (errorAt, OpCodes.Ldloc, htpop); scg.ilGen.Emit (errorAt, OpCodes.Ldloc, htpop);
scg.ilGen.Emit (errorAt, OpCodes.Call, type.GetHeapTrackerPopMeth ()); type.CallHeapTrackerPopMeth (errorAt, scg.ilGen);
} else { } else {
/* /*

View File

@ -1504,6 +1504,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
/** /**
* @brief Get heap tracking type. * @brief Get heap tracking type.
* null indicates there is no heap tracker for the type.
*/ */
public virtual Type ToHeapTrackerType () public virtual Type ToHeapTrackerType ()
{ {
@ -1511,15 +1512,15 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
} }
public virtual ConstructorInfo GetHeapTrackerCtor () public virtual ConstructorInfo GetHeapTrackerCtor ()
{ {
return null; throw new ApplicationException("no GetHeapTrackerCtor for " + this.GetType());
} }
public virtual MethodInfo GetHeapTrackerPopMeth () public virtual void CallHeapTrackerPopMeth (Token errorAt, ScriptMyILGen ilGen)
{ {
return null; throw new ApplicationException("no CallHeapTrackerPopMeth for " + this.GetType());
} }
public virtual MethodInfo GetHeapTrackerPushMeth () public virtual void CallHeapTrackerPushMeth(Token errorAt, ScriptMyILGen ilGen)
{ {
return null; throw new ApplicationException("no CallHeapTrackerPushMeth for " + this.GetType());
} }
} }
@ -1610,8 +1611,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
public class TokenTypeList : TokenType { public class TokenTypeList : TokenType {
private static readonly FieldInfo iarListsFieldInfo = typeof (XMRInstArrays).GetField ("iarLists"); private static readonly FieldInfo iarListsFieldInfo = typeof (XMRInstArrays).GetField ("iarLists");
private static readonly ConstructorInfo htListCtor = typeof (HeapTrackerList).GetConstructor (new Type [] { typeof (XMRInstAbstract) }); private static readonly ConstructorInfo htListCtor = typeof (HeapTrackerList).GetConstructor (new Type [] { typeof (XMRInstAbstract) });
private static readonly MethodInfo htListPopMeth = typeof (HeapTrackerList).GetMethod ("Pop", new Type[] { typeof (LSL_List) });
private static readonly MethodInfo htListPushMeth = typeof (HeapTrackerList).GetMethod ("Push", new Type[0]);
public TokenTypeList (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { } public TokenTypeList (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { }
public TokenTypeList (Token original) : base (original) { } public TokenTypeList (Token original) : base (original) { }
@ -1624,14 +1623,12 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
} }
public override Type ToHeapTrackerType () { return typeof (HeapTrackerList); } public override Type ToHeapTrackerType () { return typeof (HeapTrackerList); }
public override ConstructorInfo GetHeapTrackerCtor () { return htListCtor; } public override ConstructorInfo GetHeapTrackerCtor () { return htListCtor; }
public override MethodInfo GetHeapTrackerPopMeth () { return htListPopMeth; } public override void CallHeapTrackerPopMeth (Token errorAt, ScriptMyILGen ilGen) { HeapTrackerList.GenPop(errorAt, ilGen); }
public override MethodInfo GetHeapTrackerPushMeth () { return htListPushMeth; } public override void CallHeapTrackerPushMeth (Token errorAt, ScriptMyILGen ilGen) { HeapTrackerList.GenPush(errorAt, ilGen); }
} }
public class TokenTypeObject : TokenType { public class TokenTypeObject : TokenType {
private static readonly FieldInfo iarObjectsFieldInfo = typeof (XMRInstArrays).GetField ("iarObjects"); private static readonly FieldInfo iarObjectsFieldInfo = typeof (XMRInstArrays).GetField ("iarObjects");
private static readonly ConstructorInfo htObjectCtor = typeof (HeapTrackerObject).GetConstructor (new Type [] { typeof (XMRInstAbstract) }); private static readonly ConstructorInfo htObjectCtor = typeof (HeapTrackerObject).GetConstructor (new Type [] { typeof (XMRInstAbstract) });
private static readonly MethodInfo htObjectPopMeth = typeof (HeapTrackerObject).GetMethod ("Pop", new Type[] { typeof (object) });
private static readonly MethodInfo htObjectPushMeth = typeof (HeapTrackerObject).GetMethod ("Push", new Type[0]);
public TokenTypeObject (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { } public TokenTypeObject (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { }
public TokenTypeObject (Token original) : base (original) { } public TokenTypeObject (Token original) : base (original) { }
@ -1644,8 +1641,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
} }
public override Type ToHeapTrackerType () { return typeof (HeapTrackerObject); } public override Type ToHeapTrackerType () { return typeof (HeapTrackerObject); }
public override ConstructorInfo GetHeapTrackerCtor () { return htObjectCtor; } public override ConstructorInfo GetHeapTrackerCtor () { return htObjectCtor; }
public override MethodInfo GetHeapTrackerPopMeth () { return htObjectPopMeth; } public override void CallHeapTrackerPopMeth(Token errorAt, ScriptMyILGen ilGen) { HeapTrackerObject.GenPop (errorAt, ilGen); }
public override MethodInfo GetHeapTrackerPushMeth () { return htObjectPushMeth; } public override void CallHeapTrackerPushMeth(Token errorAt, ScriptMyILGen ilGen) { HeapTrackerObject.GenPush(errorAt, ilGen); }
} }
public class TokenTypeRot : TokenType { public class TokenTypeRot : TokenType {
private static readonly FieldInfo iarRotationsFieldInfo = typeof (XMRInstArrays).GetField ("iarRotations"); private static readonly FieldInfo iarRotationsFieldInfo = typeof (XMRInstArrays).GetField ("iarRotations");
@ -1663,8 +1660,6 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
public class TokenTypeStr : TokenType { public class TokenTypeStr : TokenType {
private static readonly FieldInfo iarStringsFieldInfo = typeof (XMRInstArrays).GetField ("iarStrings"); private static readonly FieldInfo iarStringsFieldInfo = typeof (XMRInstArrays).GetField ("iarStrings");
private static readonly ConstructorInfo htStringCtor = typeof (HeapTrackerString).GetConstructor (new Type [] { typeof (XMRInstAbstract) }); private static readonly ConstructorInfo htStringCtor = typeof (HeapTrackerString).GetConstructor (new Type [] { typeof (XMRInstAbstract) });
private static readonly MethodInfo htStringPopMeth = typeof (HeapTrackerString).GetMethod ("Pop", new Type[] { typeof (string) });
private static readonly MethodInfo htStringPushMeth = typeof (HeapTrackerString).GetMethod ("Push", new Type[0]);
public TokenTypeStr (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { } public TokenTypeStr (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { }
public TokenTypeStr (Token original) : base (original) { } public TokenTypeStr (Token original) : base (original) { }
@ -1677,8 +1672,8 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
} }
public override Type ToHeapTrackerType () { return typeof (HeapTrackerString); } public override Type ToHeapTrackerType () { return typeof (HeapTrackerString); }
public override ConstructorInfo GetHeapTrackerCtor () { return htStringCtor; } public override ConstructorInfo GetHeapTrackerCtor () { return htStringCtor; }
public override MethodInfo GetHeapTrackerPopMeth () { return htStringPopMeth; } public override void CallHeapTrackerPopMeth(Token errorAt, ScriptMyILGen ilGen) { HeapTrackerString.GenPop(errorAt, ilGen); }
public override MethodInfo GetHeapTrackerPushMeth () { return htStringPushMeth; } public override void CallHeapTrackerPushMeth (Token errorAt, ScriptMyILGen ilGen) { HeapTrackerString.GenPush(errorAt, ilGen); }
} }
public class TokenTypeUndef : TokenType { // for the 'undef' constant, ie, null object pointer public class TokenTypeUndef : TokenType { // for the 'undef' constant, ie, null object pointer
public TokenTypeUndef (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { } public TokenTypeUndef (TokenErrorMessage emsg, string file, int line, int posn) : base (emsg, file, line, posn) { }

View File

@ -54,7 +54,7 @@ namespace OpenSim.Region.ScriptEngine.XMREngine {
} }
bool https = uri.Scheme == "https"; bool https = uri.Scheme == "https";
if (!https && (uri.Scheme != "http")) { if (!https && (uri.Scheme != "http")) {
throw new WebException ("only support " + supported + ", not " + uri.Scheme); throw new WebException ("only support " + supported + ", not " + uri.Scheme + " in " + requestUrl);
} }
string host = uri.Host; string host = uri.Host;
int port = uri.Port; int port = uri.Port;

View File

@ -25,11 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.XMREngine;
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Reflection.Emit; using System.Reflection.Emit;
@ -43,9 +39,18 @@ using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
namespace OpenSim.Region.ScriptEngine.XMREngine namespace OpenSim.Region.ScriptEngine.XMREngine
{ {
/**
* One instance of this class for lsl base objects that take a variable
* amount of memory. They are what the script-visible list,object,string
* variables are declared as at the CIL level. Generally, temp vars used
* by the compiler get their basic type (list,object,string).
*
* Note that the xmr arrays and script-defined objects have their own
* heap tracking built in so do not need any of this stuff.
*/
public class HeapTrackerBase { public class HeapTrackerBase {
private int usage; protected int usage; // num bytes used by object
private XMRInstAbstract instance; protected XMRInstAbstract instance; // what script it is in
public HeapTrackerBase (XMRInstAbstract inst) public HeapTrackerBase (XMRInstAbstract inst)
{ {
@ -57,36 +62,78 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
{ {
usage = instance.UpdateHeapUse (usage, 0); usage = instance.UpdateHeapUse (usage, 0);
} }
protected void NewUse (int newuse)
{
usage = instance.UpdateHeapUse (usage, newuse);
}
} }
/**
* Wrapper around lists to keep track of how much memory they use.
*/
public class HeapTrackerList : HeapTrackerBase { public class HeapTrackerList : HeapTrackerBase {
private LSL_List value; private static FieldInfo listValueField = typeof (HeapTrackerList).GetField ("value");
private static MethodInfo listSaveMethod = typeof (HeapTrackerList).GetMethod ("Save");
public LSL_List value;
public HeapTrackerList (XMRInstAbstract inst) : base (inst) { } public HeapTrackerList (XMRInstAbstract inst) : base (inst) { }
public void Pop (LSL_List lis) // generate CIL code to pop the value from the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// new value pushed on CIL stack
// output:
// 'this' pointer popped from stack
// new value popped from CIL stack
// heap usage updated
public static void GenPop (Token errorAt, ScriptMyILGen ilGen)
{ {
NewUse (Size (lis)); ilGen.Emit(errorAt, OpCodes.Call, listSaveMethod);
}
// generate CIL code to push the value on the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// output:
// 'this' pointer popped from stack
// value pushed on CIL stack replacing 'this' pointer
// returns typeof value pushed on stack
public static Type GenPush (Token errorAt, ScriptMyILGen ilGen)
{
ilGen.Emit (errorAt, OpCodes.Ldfld, listValueField);
return typeof (LSL_List);
}
public void Save (LSL_List lis)
{
int newuse = Size (lis);
usage = instance.UpdateHeapUse (usage, newuse);
value = lis; value = lis;
} }
public LSL_List Push () //private static int counter = 5;
{
return value;
}
public static int Size (LSL_List lis) public static int Size (LSL_List lis)
{ {
return (!typeof (LSL_List).IsValueType && (lis == null)) ? 0 : lis.Size; // VS2017 in debug mode seems to have a problem running this statement quickly:
//SLOW: return (!typeof(LSL_List).IsValueType && (lis == null)) ? 0 : lis.Size;
//FAST: return 33;
//SLOW: return (lis == null) ? 0 : 99;
//FAST: return ++ counter;
// VS2017 in debug mode seems content to run this quickly though:
try {
return lis.Size;
} catch {
return 0;
}
} }
} }
/**
* Wrapper around objects to keep track of how much memory they use.
*/
public class HeapTrackerObject : HeapTrackerBase { public class HeapTrackerObject : HeapTrackerBase {
private static FieldInfo objectValueField = typeof (HeapTrackerObject).GetField ("value");
private static MethodInfo objectSaveMethod = typeof (HeapTrackerObject).GetMethod ("Save");
public const int HT_CHAR = 2; public const int HT_CHAR = 2;
public const int HT_DELE = 8; public const int HT_DELE = 8;
public const int HT_DOUB = 8; public const int HT_DOUB = 8;
@ -96,21 +143,44 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
public const int HT_VEC = HT_DOUB * 3; public const int HT_VEC = HT_DOUB * 3;
public const int HT_ROT = HT_DOUB * 4; public const int HT_ROT = HT_DOUB * 4;
private object value; public object value;
public HeapTrackerObject (XMRInstAbstract inst) : base (inst) { } public HeapTrackerObject (XMRInstAbstract inst) : base (inst) { }
public void Pop (object obj) // generate CIL code to pop the value from the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// new value pushed on CIL stack
// output:
// 'this' pointer popped from stack
// new value popped from CIL stack
// heap usage updated
public static void GenPop (Token errorAt, ScriptMyILGen ilGen)
{ {
NewUse (Size (obj)); ilGen.Emit(errorAt, OpCodes.Call, objectSaveMethod);
}
// generate CIL code to push the value on the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// output:
// 'this' pointer popped from stack
// value pushed on CIL stack replacing 'this' pointer
// returns typeof value pushed on stack
public static Type GenPush (Token errorAt, ScriptMyILGen ilGen)
{
ilGen.Emit (errorAt, OpCodes.Ldfld, objectValueField);
return typeof (object);
}
public void Save (object obj)
{
int newuse = Size (obj);
usage = instance.UpdateHeapUse (usage, newuse);
value = obj; value = obj;
} }
public object Push () // public so it can be used by XMRArray
{
return value;
}
public static int Size (object obj) public static int Size (object obj)
{ {
if (obj == null) return 0; if (obj == null) return 0;
@ -148,20 +218,48 @@ namespace OpenSim.Region.ScriptEngine.XMREngine
} }
} }
/**
* Wrapper around strings to keep track of how much memory they use.
*/
public class HeapTrackerString : HeapTrackerBase { public class HeapTrackerString : HeapTrackerBase {
private string value; private static FieldInfo stringValueField = typeof (HeapTrackerString).GetField ("value");
private static MethodInfo stringSaveMethod = typeof (HeapTrackerString).GetMethod ("Save");
public string value;
public HeapTrackerString (XMRInstAbstract inst) : base (inst) { } public HeapTrackerString (XMRInstAbstract inst) : base (inst) { }
public void Pop (string str) // generate CIL code to pop the value from the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// new value pushed on CIL stack
// output:
// 'this' pointer popped from stack
// new value popped from CIL stack
// heap usage updated
public static void GenPop (Token errorAt, ScriptMyILGen ilGen)
{ {
NewUse (Size (str)); ilGen.Emit (errorAt, OpCodes.Call, stringSaveMethod);
value = str;
} }
public string Push () // generate CIL code to push the value on the CIL stack
// input:
// 'this' pointer already pushed on CIL stack
// output:
// 'this' pointer popped from stack
// value pushed on CIL stack replacing 'this' pointer
// returns typeof value pushed on stack
public static Type GenPush (Token errorAt, ScriptMyILGen ilGen)
{ {
return value; ilGen.Emit (errorAt, OpCodes.Ldfld, stringValueField);
return typeof (string);
}
public void Save (string str)
{
int newuse = Size (str);
usage = instance.UpdateHeapUse (usage, newuse);
value = str;
} }
public static int Size (string str) public static int Size (string str)