浏览代码

More perf tuning

Brad Robinson 11 年之前
父节点
当前提交
670590e38f
共有 2 个文件被更改,包括 74 次插入202 次删除
  1. 65 95
      PetaJson.cs
  2. 9 107
      PetaJsonEmit.cs

+ 65 - 95
PetaJson.cs

@@ -1413,98 +1413,13 @@ namespace PetaJson
 
         }
 
-        public class RewindableTextReader
-        {
-            public RewindableTextReader(TextReader underlying)
-            {
-                _underlying = underlying;
-                FillBuffer();
-            }
-
-            TextReader _underlying;
-            char[] _buf = new char[4096];
-            int _pos;
-            int _bufUsed;
-            StringBuilder _rewindBuffer;
-            int _rewindBufferPos;
-
-            void FillBuffer()
-            {
-                _bufUsed = _underlying.Read(_buf, 0, _buf.Length);
-                _pos = 0;
-            }
-
-            public char ReadChar()
-            {
-                if (_rewindBuffer == null)
-                {
-                    if (_pos >= _bufUsed)
-                    {
-                        if (_bufUsed > 0)
-                        {
-                            FillBuffer();
-                        }
-                        if (_bufUsed == 0)
-                        {
-                            return '\0';
-                        }
-                    }
-
-                    // Next
-                    return _buf[_pos++];
-                }
-
-                if (_rewindBufferPos < _rewindBuffer.Length)
-                {
-                    return _rewindBuffer[_rewindBufferPos++];
-                }
-                else
-                {
-                    if (_pos >= _bufUsed && _bufUsed > 0)
-                        FillBuffer();
-
-                    char ch = _bufUsed == 0 ? '\0' : _buf[_pos++];
-                    _rewindBuffer.Append(ch);
-                    _rewindBufferPos++;
-                    return ch;
-                }
-            }
-
-            Stack<int> _bookmarks = new Stack<int>();
-
-            public void CreateBookmark()
-            {
-                if (_rewindBuffer == null)
-                {
-                    _rewindBuffer = new StringBuilder();
-                    _rewindBufferPos = 0;
-                }
-
-                _bookmarks.Push(_rewindBufferPos);
-            }
-
-            public void RewindToBookmark()
-            {
-                _rewindBufferPos = _bookmarks.Pop();
-            }
-
-            public void DiscardBookmark()
-            {
-                _bookmarks.Pop();
-                if (_bookmarks.Count == 0)
-                {
-                    _rewindBuffer = null;
-                    _rewindBufferPos = 0;
-                }
-            }
-        }
-
- 
         public class Tokenizer
         {
             public Tokenizer(TextReader r, JsonOptions options)
             {
-                _reader = new RewindableTextReader(r);
+                _underlying = r;
+                FillBuffer();
+
                 _options = options;
 
                 // Load up
@@ -1512,10 +1427,16 @@ namespace PetaJson
                 NextToken();
             }
 
-            RewindableTextReader _reader;
             JsonOptions _options;
             StringBuilder _sb = new StringBuilder();
 
+            TextReader _underlying;
+            char[] _buf = new char[4096];
+            int _pos;
+            int _bufUsed;
+            StringBuilder _rewindBuffer;
+            int _rewindBufferPos;
+
             JsonLineOffset _currentCharPos;
             JsonLineOffset CurrentTokenPos;
             char _currentChar;
@@ -1579,6 +1500,7 @@ namespace PetaJson
                     CurrentToken = tokenizer.CurrentToken;
                     _string = tokenizer.String;
                     _literalKind = tokenizer.LiteralKind;
+                    _rewindBufferPos = tokenizer._rewindBufferPos;
                 }
 
                 public void Apply(Tokenizer tokenizer)
@@ -1590,6 +1512,7 @@ namespace PetaJson
                     tokenizer.CurrentToken = CurrentToken;
                     tokenizer.String = _string;
                     tokenizer.LiteralKind = _literalKind;
+                    tokenizer._rewindBufferPos = _rewindBufferPos;
                 }
 
                 public JsonLineOffset _currentCharPos;
@@ -1599,6 +1522,7 @@ namespace PetaJson
                 public Token CurrentToken;
                 public LiteralKind _literalKind;
                 public string _string;
+                public int _rewindBufferPos;
             }
 
             Stack<ReaderState> _bookmarks = new Stack<ReaderState>();
@@ -1606,25 +1530,71 @@ namespace PetaJson
             public void CreateBookmark()
             {
                 _bookmarks.Push(new ReaderState(this));
-                _reader.CreateBookmark();
+                if (_rewindBuffer == null)
+                {
+                    _rewindBuffer = new StringBuilder();
+                    _rewindBufferPos = 0;
+                }
             }
 
             public void DiscardBookmark()
             {
                 _bookmarks.Pop();
-                _reader.DiscardBookmark();
+                if (_bookmarks.Count == 0)
+                {
+                    _rewindBuffer = null;
+                    _rewindBufferPos = 0;
+                }
             }
 
             public void RewindToBookmark()
             {
                 _bookmarks.Pop().Apply(this);
-                _reader.RewindToBookmark();
             }
 
-            char NextChar()
+            void FillBuffer()
+            {
+                _bufUsed = _underlying.Read(_buf, 0, _buf.Length);
+                _pos = 0;
+            }
+
+            public char NextChar()
             {
-                _currentCharPos.Offset++;
-                return _currentChar = _reader.ReadChar();
+                if (_rewindBuffer == null)
+                {
+                    if (_pos >= _bufUsed)
+                    {
+                        if (_bufUsed > 0)
+                        {
+                            FillBuffer();
+                        }
+                        if (_bufUsed == 0)
+                        {
+                            return _currentChar = '\0';
+                        }
+                    }
+
+                    // Next
+                    _currentCharPos.Offset++;
+                    return _currentChar = _buf[_pos++];
+                }
+
+                if (_rewindBufferPos < _rewindBuffer.Length)
+                {
+                    _currentCharPos.Offset++;
+                    return _currentChar = _rewindBuffer[_rewindBufferPos++];
+                }
+                else
+                {
+                    if (_pos >= _bufUsed && _bufUsed > 0)
+                        FillBuffer();
+
+                    _currentChar = _bufUsed == 0 ? '\0' : _buf[_pos++];
+                    _rewindBuffer.Append(_currentChar);
+                    _rewindBufferPos++;
+                    _currentCharPos.Offset++;
+                    return _currentChar;
+                }
             }
 
             public void NextToken()

+ 9 - 107
PetaJsonEmit.cs

@@ -309,31 +309,29 @@ namespace PetaJson
                     il.Emit(OpCodes.Ldarg_1);
                     il.Emit(OpCodes.Castclass, type);
 
-                    if (m.MemberType == typeof(string))
+                    Action<string> callHelper = helperName =>
                     {
                         // check we have a string
                         il.Emit(OpCodes.Ldarg_0);
-                        il.Emit(OpCodes.Call, typeof(Emit).GetMethod("GetLiteralString", new Type[] { typeof(IJsonReader) }));
+                        il.Emit(OpCodes.Call, typeof(Emit).GetMethod(helperName, new Type[] { typeof(IJsonReader) }));
 
                         il.Emit(OpCodes.Ldarg_0);
                         il.Emit(OpCodes.Callvirt, typeof(IJsonReader).GetMethod("NextToken", new Type[] { }));
+                    };
+
+                    if (m.MemberType == typeof(string))
+                    {
+                        callHelper("GetLiteralString");
                     }
 
                     else if (m.MemberType == typeof(bool))
                     {
-                        il.Emit(OpCodes.Ldarg_0);
-                        il.Emit(OpCodes.Call, typeof(Emit).GetMethod("GetLiteralBool", new Type[] { typeof(IJsonReader) }));
-
-                        il.Emit(OpCodes.Ldarg_0);
-                        il.Emit(OpCodes.Callvirt, typeof(IJsonReader).GetMethod("NextToken", new Type[] { }));
+                        callHelper("GetLiteralBool");
                     }
 
                     else if (m.MemberType == typeof(char))
                     {
-                        il.Emit(OpCodes.Ldarg_0);
-                        il.Emit(OpCodes.Call, typeof(Emit).GetMethod("GetLiteralChar", new Type[] { typeof(IJsonReader) }));
-                        il.Emit(OpCodes.Ldarg_0);
-                        il.Emit(OpCodes.Callvirt, typeof(IJsonReader).GetMethod("NextToken", new Type[] { }));
+                        callHelper("GetLiteralChar");
                     }
 
                     else if (numericTypes.Contains(m.MemberType))
@@ -369,19 +367,6 @@ namespace PetaJson
                         il.Emit(OpCodes.Stfld, fi);
                     }
 
-                    // Cast/unbox the target object and store in local variable
-                    /*
-                    var locTypedObj = il.DeclareLocal(type);
-                    il.Emit(OpCodes.Ldarg_1);
-                    il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);
-                    il.Emit(OpCodes.Stloc, locTypedObj);
-
-                    // Get Invariant CultureInfo
-                    var locInvariant = il.DeclareLocal(typeof(IFormatProvider));
-                    il.Emit(OpCodes.Call, typeof(CultureInfo).GetProperty("InvariantCulture").GetGetMethod());
-                    il.Emit(OpCodes.Stloc, locInvariant);
-                        */
-
                     il.Emit(OpCodes.Ret);
 
                     // Store the handler in map
@@ -456,87 +441,4 @@ namespace PetaJson
 
         }
     }
-
-    /*
-            static MethodInfo fnChangeType = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(Object), typeof(Type) });
-            static MethodInfo fnGetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
-
-            public static Action<object, object> CreateSetter(PropertyInfo pi)
-            {
-                var m = new DynamicMethod("dynamic_property_setter_" + pi.DeclaringType.Name + "_" + pi.Name, null, new Type[] { typeof(object), typeof(object) }, true);
-                var il = m.GetILGenerator();
-
-                il.Emit(OpCodes.Ldarg_0);
-                il.Emit(pi.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, pi.DeclaringType);
-
-                il.Emit(OpCodes.Ldarg_1);
-                il.Emit(OpCodes.Ldtoken, pi.PropertyType);
-                il.Emit(OpCodes.Call, fnGetTypeFromHandle);
-                il.Emit(OpCodes.Call, fnChangeType);
-                il.Emit(pi.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, pi.PropertyType);
-
-                il.Emit(OpCodes.Callvirt, pi.GetSetMethod());
-                il.Emit(OpCodes.Ret);
-
-                return (Action<object, object>)m.CreateDelegate(typeof(Action<object, object>));
-            }
-
-            public static Action<object, object> CreateSetter(FieldInfo fi)
-            {
-                var m = new DynamicMethod("dynamic_field_setter_" + fi.DeclaringType.Name + "_" + fi.Name, null, new Type[] { typeof(object), typeof(object) }, true);
-                var il = m.GetILGenerator();
-
-
-                var fnChangeType = typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(Object), typeof(Type) });
-                var fnGetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
-
-                il.Emit(OpCodes.Ldarg_0);
-                il.Emit(fi.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, fi.DeclaringType);
-
-                il.Emit(OpCodes.Ldarg_1);
-                il.Emit(OpCodes.Ldtoken, fi.FieldType);
-                il.Emit(OpCodes.Call, fnGetTypeFromHandle);
-                il.Emit(OpCodes.Call, fnChangeType);
-                il.Emit(fi.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, fi.FieldType);
-
-                il.Emit(OpCodes.Stfld, fi);
-                il.Emit(OpCodes.Ret);
-
-                return (Action<object, object>)m.CreateDelegate(typeof(Action<object, object>));
-            }
-
-            public static Func<object, object> CreateGetter(PropertyInfo pi)
-            {
-                var m = new DynamicMethod("dynamic_property_setter_" + pi.DeclaringType.Name + "_" + pi.Name, typeof(object), new Type[] { typeof(object) }, true);
-                var il = m.GetILGenerator();
-
-                il.Emit(OpCodes.Ldarg_0);
-                il.Emit(pi.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, pi.DeclaringType);
-
-                il.Emit(OpCodes.Callvirt, pi.GetGetMethod());
-
-                if (pi.PropertyType.IsValueType)
-                    il.Emit(OpCodes.Box, pi.PropertyType);
-
-                il.Emit(OpCodes.Ret);
-
-                return (Func<object, object>)m.CreateDelegate(typeof(Func<object, object>));
-            }
-            public static Func<object, object> CreateGetter(FieldInfo fi)
-            {
-                var m = new DynamicMethod("dynamic_field_setter_" + fi.DeclaringType.Name + "_" + fi.Name, typeof(object), new Type[] { typeof(object) }, true);
-                var il = m.GetILGenerator();
-
-                il.Emit(OpCodes.Ldarg_0);
-                il.Emit(fi.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, fi.DeclaringType);
-
-                il.Emit(OpCodes.Ldfld, fi);
-                if (fi.FieldType.IsValueType)
-                    il.Emit(OpCodes.Box, fi.FieldType);
-
-                il.Emit(OpCodes.Ret);
-
-                return (Func<object, object>)m.CreateDelegate(typeof(Func<object, object>));
-            }
-     */
 }