From 974178a162291879ab57ac39e490a8aea3dd0ea5 Mon Sep 17 00:00:00 2001 From: JamesNK Date: Tue, 29 Dec 2009 02:53:53 +0000 Subject: [PATCH] -Performance --- .../Newtonsoft.Json.Tests.Net20.csproj | 11 ++ Src/Newtonsoft.Json.Tests/PerformanceTests.cs | 162 ++++++++++++------ Src/Newtonsoft.Json.Tests/bunny_pancake.jpg | Bin 0 -> 18482 bytes Src/Newtonsoft.Json/Bson/BsonWriter.cs | 60 +++++-- Src/Newtonsoft.Json/JsonWriter.cs | 6 +- Src/Newtonsoft.Json/Linq/JContainer.cs | 3 +- Src/Newtonsoft.Json/Linq/JObject.cs | 10 +- .../Utilities/JavaScriptUtils.cs | 114 ++++++------ Src/Newtonsoft.Json/Utilities/StringUtils.cs | 23 ++- 9 files changed, 247 insertions(+), 142 deletions(-) create mode 100644 Src/Newtonsoft.Json.Tests/bunny_pancake.jpg diff --git a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj index 6a6bbf6f..84ac9c5f 100644 --- a/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj +++ b/Src/Newtonsoft.Json.Tests/Newtonsoft.Json.Tests.Net20.csproj @@ -77,22 +77,30 @@ + + + + + + + + @@ -105,7 +113,9 @@ + + @@ -189,6 +199,7 @@ + diff --git a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs index 5c1cd929..91f5aa9d 100644 --- a/Src/Newtonsoft.Json.Tests/PerformanceTests.cs +++ b/Src/Newtonsoft.Json.Tests/PerformanceTests.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Diagnostics; - -using Newtonsoft.Json; using System.IO; using System.Web.Script.Serialization; @@ -16,6 +14,13 @@ using Newtonsoft.Json.Bson; namespace Newtonsoft.Json.Tests { + public class Image + { + public string FileName { get; set; } + public string Title { get; set; } + public byte[] Data { get; set; } + } + public class PerformanceTests : TestFixtureBase { private const int Iterations = 100; @@ -70,6 +75,50 @@ namespace Newtonsoft.Json.Tests [Test] public void Serialize() + { + TestClass test = CreateSerializationObject(); + + BenchmarkSerializeMethod(SerializeMethod.JsonNet, test); + BenchmarkSerializeMethod(SerializeMethod.JsonNetBinary, test); + BenchmarkSerializeMethod(SerializeMethod.JavaScriptSerializer, test); + BenchmarkSerializeMethod(SerializeMethod.DataContractJsonSerializer, test); + } + + [Test] + public void Deserialize() + { + BenchmarkDeserializeMethod(SerializeMethod.JsonNet, JsonText); + BenchmarkDeserializeMethod(SerializeMethod.JsonNetBinary, MiscellaneousUtils.HexToBytes(BsonHex)); + BenchmarkDeserializeMethod(SerializeMethod.JavaScriptSerializer, JsonText); + BenchmarkDeserializeMethod(SerializeMethod.DataContractJsonSerializer, JsonText); + } + + [Test] + public void SerializeDataSize() + { + Image image = new Image(); + image.Data = System.IO.File.ReadAllBytes(@"..\..\bunny_pancake.jpg"); + image.FileName = "bunny_pancake.jpg"; + image.Title = "I have no idea what you are talking about so here's a bunny with a pancake on its head"; + + string json = JsonConvert.SerializeObject(image, Formatting.None); + byte[] jsonBytes = Encoding.UTF8.GetBytes(json); + + MemoryStream ms = new MemoryStream(); + JsonSerializer serializer = new JsonSerializer(); + BsonWriter writer = new BsonWriter(ms); + + serializer.Serialize(writer, image); + writer.Flush(); + + byte[] bsonBytes = ms.ToArray(); + + Console.WriteLine("Image size: {0} bytes", image.Data.Length); + Console.WriteLine("JSON size: {0} bytes", jsonBytes.Length); + Console.WriteLine("BSON size: {0} bytes", bsonBytes.Length); + } + + private TestClass CreateSerializationObject() { TestClass test = new TestClass(); @@ -90,20 +139,7 @@ namespace Newtonsoft.Json.Tests address.Entered = DateTime.Now.AddDays(-2); address.Address = "array 2 address"; test.Addresses.Add(address); - - BenchmarkSerializeMethod(SerializeMethod.JsonNet, test); - BenchmarkSerializeMethod(SerializeMethod.JsonNetBinary, test); - BenchmarkSerializeMethod(SerializeMethod.JavaScriptSerializer, test); - BenchmarkSerializeMethod(SerializeMethod.DataContractJsonSerializer, test); - } - - [Test] - public void Deserialize() - { - BenchmarkDeserializeMethod(SerializeMethod.JsonNet, JsonText); - BenchmarkDeserializeMethod(SerializeMethod.JsonNetBinary, MiscellaneousUtils.HexToBytes(BsonHex)); - BenchmarkDeserializeMethod(SerializeMethod.JavaScriptSerializer, JsonText); - BenchmarkDeserializeMethod(SerializeMethod.DataContractJsonSerializer, JsonText); + return test; } public string SerializeJsonNet(object value) @@ -203,33 +239,49 @@ namespace Newtonsoft.Json.Tests return dataContractSerializer.ReadObject(ms); } + private static readonly byte[] Buffer = new byte[4096]; + + private string Serialize(SerializeMethod method, object value) + { + string json; + + switch (method) + { + case SerializeMethod.JsonNet: + json = JsonConvert.SerializeObject(value); + break; + case SerializeMethod.JsonNetBinary: + MemoryStream ms = new MemoryStream(Buffer); + JsonSerializer serializer = new JsonSerializer(); + BsonWriter writer = new BsonWriter(ms); + serializer.Serialize(writer, value); + + json = "Bytes = " + ms.Length; + break; + case SerializeMethod.JavaScriptSerializer: + json = SerializeWebExtensions(value); + break; + case SerializeMethod.DataContractJsonSerializer: + json = SerializeDataContract(value); + break; + default: + throw new ArgumentOutOfRangeException("method"); + } + + return json; + } + public void BenchmarkSerializeMethod(SerializeMethod method, object value) { + Serialize(method, value); + Stopwatch timed = new Stopwatch(); timed.Start(); string json = null; for (int x = 0; x < Iterations; x++) { - switch (method) - { - case SerializeMethod.JsonNet: - json = JsonConvert.SerializeObject(value); - break; - case SerializeMethod.JsonNetBinary: - JsonSerializer serializer = new JsonSerializer(); - MemoryStream ms = new MemoryStream(); - BsonWriter writer = new BsonWriter(ms); - serializer.Serialize(writer, value); - json = "{Bytes " + ms.Length + "}"; - break; - case SerializeMethod.JavaScriptSerializer: - json = SerializeWebExtensions(value); - break; - case SerializeMethod.DataContractJsonSerializer: - json = SerializeDataContract(value); - break; - } + json = Serialize(method, value); } timed.Stop(); @@ -248,21 +300,7 @@ namespace Newtonsoft.Json.Tests object value = null; for (int x = 0; x < Iterations; x++) { - switch (method) - { - case SerializeMethod.JsonNet: - value = DeserializeJsonNet((string)json); - break; - case SerializeMethod.JsonNetBinary: - value = DeserializeJsonNetBinary((byte[])json); - break; - case SerializeMethod.JavaScriptSerializer: - value = DeserializeWebExtensions((string)json); - break; - case SerializeMethod.DataContractJsonSerializer: - value = DeserializeDataContract((string)json); - break; - } + value = Deserialize(method, json); } timed.Stop(); @@ -272,6 +310,30 @@ namespace Newtonsoft.Json.Tests Console.WriteLine(value); Console.WriteLine(); } + + private object Deserialize(SerializeMethod method, object json) + { + object value; + + switch (method) + { + case SerializeMethod.JsonNet: + value = DeserializeJsonNet((string) json); + break; + case SerializeMethod.JsonNetBinary: + value = DeserializeJsonNetBinary((byte[]) json); + break; + case SerializeMethod.JavaScriptSerializer: + value = DeserializeWebExtensions((string) json); + break; + case SerializeMethod.DataContractJsonSerializer: + value = DeserializeDataContract((string) json); + break; + default: + throw new ArgumentOutOfRangeException("method"); + } + return value; + } } diff --git a/Src/Newtonsoft.Json.Tests/bunny_pancake.jpg b/Src/Newtonsoft.Json.Tests/bunny_pancake.jpg new file mode 100644 index 0000000000000000000000000000000000000000..59e882ca74a4c84534c82ce4c3376801fe603d53 GIT binary patch literal 18482 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 LMQ6mq{$KyuKyNhi literal 0 HcmV?d00001 diff --git a/Src/Newtonsoft.Json/Bson/BsonWriter.cs b/Src/Newtonsoft.Json/Bson/BsonWriter.cs index 575c5c16..1d7bc0c7 100644 --- a/Src/Newtonsoft.Json/Bson/BsonWriter.cs +++ b/Src/Newtonsoft.Json/Bson/BsonWriter.cs @@ -37,8 +37,13 @@ namespace Newtonsoft.Json.Bson /// public class BsonWriter : JTokenWriter { + private static readonly Encoding Encoding = Encoding.UTF8; + private readonly BinaryWriter _writer; + private byte[] _largeByteBuffer; + private int _maxChars; + /// /// Initializes a new instance of the class. /// @@ -68,7 +73,7 @@ namespace Newtonsoft.Json.Bson foreach (JProperty property in t) { _writer.Write((sbyte)GetTypeNumber(property.Value)); - WriteString(property.Name); + WriteString(property.Name, false); WriteToken(property.Value); } _writer.Write((byte)0); @@ -82,7 +87,7 @@ namespace Newtonsoft.Json.Bson foreach (JToken c in t) { _writer.Write((sbyte)GetTypeNumber(c)); - WriteString(index.ToString(CultureInfo.InvariantCulture)); + WriteString(index.ToString(CultureInfo.InvariantCulture), false); WriteToken(c); index++; } @@ -96,7 +101,7 @@ namespace Newtonsoft.Json.Bson _writer.Write(Convert.ToDouble(((JValue)t).Value, CultureInfo.InvariantCulture)); break; case JTokenType.String: - WriteStringWithLength((string)t); + WriteString((string)t, true); break; case JTokenType.Boolean: _writer.Write((bool)t); @@ -121,17 +126,37 @@ namespace Newtonsoft.Json.Bson } } - private void WriteString(string s) + private void WriteString(string s, bool includeLength) { - byte[] bytes = Encoding.UTF8.GetBytes(s); - _writer.Write(bytes); - _writer.Write((byte)0); - } + int byteCount = Encoding.GetByteCount(s); - private void WriteStringWithLength(string s) - { - _writer.Write(CalculateSizeWithLength(s, false)); - WriteString(s); + if (includeLength) + _writer.Write(CalculateSizeWithLength(byteCount, false)); + + if (_largeByteBuffer == null) + { + _largeByteBuffer = new byte[256]; + _maxChars = 256 / Encoding.GetMaxByteCount(1); + } + if (byteCount <= 256) + { + Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0); + _writer.Write(_largeByteBuffer, 0, byteCount); + } + else + { + int charCount; + int totalCharsWritten = 0; + for (int i = s.Length; i > 0; i -= charCount) + { + charCount = (i > _maxChars) ? _maxChars : i; + int count = Encoding.GetBytes(s, totalCharsWritten, charCount, _largeByteBuffer, 0); + _writer.Write(_largeByteBuffer, 0, count); + totalCharsWritten += charCount; + } + } + + _writer.Write((byte)0); } private BsonType GetTypeNumber(JToken t) @@ -164,18 +189,21 @@ namespace Newtonsoft.Json.Bson private int CalculateSize(string s) { - return Encoding.UTF8.GetByteCount(s) + 1; + return Encoding.GetByteCount(s) + 1; } private int CalculateSizeWithLength(string s, bool includeSize) + { + return CalculateSizeWithLength(Encoding.GetByteCount(s), includeSize); + } + + private int CalculateSizeWithLength(int stringByteCount, bool includeSize) { int baseSize = (includeSize) ? 5 // size bytes + terminator : 1; // terminator - int byteCount = Encoding.UTF8.GetByteCount(s); - - return baseSize + byteCount; + return baseSize + stringByteCount; } private int CalculateSize(JToken t) diff --git a/Src/Newtonsoft.Json/JsonWriter.cs b/Src/Newtonsoft.Json/JsonWriter.cs index 09d2ec5e..2a7ddc6f 100644 --- a/Src/Newtonsoft.Json/JsonWriter.cs +++ b/Src/Newtonsoft.Json/JsonWriter.cs @@ -601,9 +601,11 @@ namespace Newtonsoft.Json WriteIndentSpace(); } + WriteState writeState = WriteState; + // don't indent a property when it is the first token to be written (i.e. at the start) - if ((tokenBeingWritten == JsonToken.PropertyName && WriteState != WriteState.Start) || - WriteState == WriteState.Array || WriteState == WriteState.Constructor) + if ((tokenBeingWritten == JsonToken.PropertyName && writeState != WriteState.Start) || + writeState == WriteState.Array || writeState == WriteState.Constructor) { WriteIndent(); } diff --git a/Src/Newtonsoft.Json/Linq/JContainer.cs b/Src/Newtonsoft.Json/Linq/JContainer.cs index df4d9b57..ecd21917 100644 --- a/Src/Newtonsoft.Json/Linq/JContainer.cs +++ b/Src/Newtonsoft.Json/Linq/JContainer.cs @@ -219,8 +219,7 @@ namespace Newtonsoft.Json.Linq { yield return current; } - while (current != null - && ((current = current.Next) != null)); + while ((current = current.Next) != null); } /// diff --git a/Src/Newtonsoft.Json/Linq/JObject.cs b/Src/Newtonsoft.Json/Linq/JObject.cs index 5fb4260f..0087f473 100644 --- a/Src/Newtonsoft.Json/Linq/JObject.cs +++ b/Src/Newtonsoft.Json/Linq/JObject.cs @@ -105,10 +105,14 @@ namespace Newtonsoft.Json.Linq if (o.Type != JTokenType.Property) throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); + // looping over all properties every time isn't good + // need to think about performance here JProperty property = (JProperty)o; - bool matchingProperty = Properties().Any(p => string.Equals(p.Name, property.Name, StringComparison.Ordinal) && p != existing); - if (matchingProperty) - throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, property.Name, GetType())); + foreach (JProperty childProperty in Children()) + { + if (childProperty != existing && string.Equals(childProperty.Name, property.Name, StringComparison.Ordinal)) + throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, property.Name, GetType())); + } } internal void InternalPropertyChanged(JProperty childProperty) diff --git a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs index 8bfccdaf..1bb723aa 100644 --- a/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs @@ -35,71 +35,68 @@ namespace Newtonsoft.Json.Utilities { internal static class JavaScriptUtils { - public static void WriteEscapedJavaScriptChar(TextWriter writer, char c, char delimiter) - { - switch (c) - { - case '\t': - writer.Write(@"\t"); - break; - case '\n': - writer.Write(@"\n"); - break; - case '\r': - writer.Write(@"\r"); - break; - case '\f': - writer.Write(@"\f"); - break; - case '\b': - writer.Write(@"\b"); - break; - case '\\': - writer.Write(@"\\"); - break; - case '\u0085': // Next Line - writer.Write(@"\u0085"); - break; - case '\u2028': // Line Separator - writer.Write(@"\u2028"); - break; - case '\u2029': // Paragraph Separator - writer.Write(@"\u2029"); - break; - case '\'': - // only escape if this charater is being used as the delimiter - writer.Write((delimiter == '\'') ? @"\'" : @"'"); - break; - case '"': - // only escape if this charater is being used as the delimiter - writer.Write((delimiter == '"') ? "\\\"" : @""""); - break; - default: - if (c > '\u001f') - writer.Write(c); - else - StringUtils.WriteCharAsUnicode(writer, c); - break; - } - } - - public static void WriteEscapedJavaScriptString(TextWriter writer, string value, char delimiter, bool appendDelimiters) + public static void WriteEscapedJavaScriptString(StringBuilder writer, string value, char delimiter, bool appendDelimiters) { // leading delimiter if (appendDelimiters) - writer.Write(delimiter); + writer.Append(delimiter); if (value != null) { for (int i = 0; i < value.Length; i++) { - WriteEscapedJavaScriptChar(writer, value[i], delimiter); + char c = value[i]; + + switch (c) + { + case '\t': + writer.Append(@"\t"); + break; + case '\n': + writer.Append(@"\n"); + break; + case '\r': + writer.Append(@"\r"); + break; + case '\f': + writer.Append(@"\f"); + break; + case '\b': + writer.Append(@"\b"); + break; + case '\\': + writer.Append(@"\\"); + break; + case '\u0085': // Next Line + writer.Append(@"\u0085"); + break; + case '\u2028': // Line Separator + writer.Append(@"\u2028"); + break; + case '\u2029': // Paragraph Separator + writer.Append(@"\u2029"); + break; + case '\'': + // only escape if this charater is being used as the delimiter + writer.Append((delimiter == '\'') ? @"\'" : @"'"); + break; + case '"': + // only escape if this charater is being used as the delimiter + writer.Append((delimiter == '"') ? "\\\"" : @""""); + break; + default: + if (c > '\u001f') + writer.Append(c); + else + StringUtils.WriteCharAsUnicode(writer, c); + break; + } } } // trailing delimiter if (appendDelimiters) - writer.Write(delimiter); + writer.Append(delimiter); } public static string ToEscapedJavaScriptString(string value) @@ -109,11 +106,14 @@ namespace Newtonsoft.Json.Utilities public static string ToEscapedJavaScriptString(string value, char delimiter, bool appendDelimiters) { - using (StringWriter w = StringUtils.CreateStringWriter(StringUtils.GetLength(value) ?? 16)) - { - WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters); - return w.ToString(); - } + int length = value.Length; + if (appendDelimiters) + length += 2; + + StringBuilder builder = new StringBuilder(length); + + WriteEscapedJavaScriptString(builder, value, delimiter, appendDelimiters); + return builder.ToString(); } } } \ No newline at end of file diff --git a/Src/Newtonsoft.Json/Utilities/StringUtils.cs b/Src/Newtonsoft.Json/Utilities/StringUtils.cs index 35d3cf18..79b19a89 100644 --- a/Src/Newtonsoft.Json/Utilities/StringUtils.cs +++ b/Src/Newtonsoft.Json/Utilities/StringUtils.cs @@ -325,14 +325,13 @@ namespace Newtonsoft.Json.Utilities public static string ToCharAsUnicode(char c) { - using (StringWriter w = new StringWriter(CultureInfo.InvariantCulture)) - { - WriteCharAsUnicode(w, c); - return w.ToString(); - } + StringBuilder builder = new StringBuilder(); + WriteCharAsUnicode(builder, c); + + return builder.ToString(); } - public static void WriteCharAsUnicode(TextWriter writer, char c) + public static void WriteCharAsUnicode(StringBuilder writer, char c) { ValidationUtils.ArgumentNotNull(writer, "writer"); @@ -341,12 +340,12 @@ namespace Newtonsoft.Json.Utilities char h3 = MathUtils.IntToHex((c >> 4) & '\x000f'); char h4 = MathUtils.IntToHex(c & '\x000f'); - writer.Write('\\'); - writer.Write('u'); - writer.Write(h1); - writer.Write(h2); - writer.Write(h3); - writer.Write(h4); + writer.Append('\\'); + writer.Append('u'); + writer.Append(h1); + writer.Append(h2); + writer.Append(h3); + writer.Append(h4); } public static TSource ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, string testValue)