-Improved large JArray performance

-Improved JTokenReader performance
This commit is contained in:
James Newton-King
2016-03-28 14:14:07 +13:00
parent 029e36e7e4
commit 3a412e5ab2
10 changed files with 117 additions and 43 deletions
@@ -301,6 +301,77 @@ namespace Newtonsoft.Json.Tests
return result;
}
[Test]
public void LargeArrayJTokenPathPerformance()
{
JArray a = new JArray();
for (int i = 0; i < 100000; i++)
{
a.Add(i);
}
JToken first = a.First;
JToken last = a.Last;
int interations = 1000;
TimeOperation(() =>
{
string p = null;
for (int i = 0; i < interations; i++)
{
p = first.Path;
}
return p;
}, "First");
TimeOperation(() =>
{
string p = null;
for (int i = 0; i < interations; i++)
{
p = last.Path;
}
return p;
}, "Last");
}
[Test]
public void LargeArrayAddPerformance()
{
JArray a1 = new JArray();
JArray a2 = new JArray();
for (int i = 0; i < 100000; i++)
{
a2.Add(i);
}
int interations = 1000;
TimeOperation(() =>
{
for (int i = 0; i < interations; i++)
{
a1.Add(interations);
}
return a1;
}, "Small");
TimeOperation(() =>
{
for (int i = 0; i < interations; i++)
{
a2.Add(interations);
}
return a2;
}, "Large");
}
[Test]
public void BuildJObject()
{
+5
View File
@@ -270,6 +270,11 @@ namespace Newtonsoft.Json.Linq
set { SetItem(index, value); }
}
internal override int IndexOfItem(JToken item)
{
return _values.IndexOfReference(item);
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
IEnumerable a = (IsMultiContent(content) || content is JArray)
+5
View File
@@ -48,6 +48,11 @@ namespace Newtonsoft.Json.Linq
get { return _values; }
}
internal override int IndexOfItem(JToken item)
{
return _values.IndexOfReference(item);
}
internal override void MergeItem(object content, JsonMergeSettings settings)
{
JConstructor c = content as JConstructor;
+1 -24
View File
@@ -351,30 +351,7 @@ namespace Newtonsoft.Json.Linq
return item;
}
private class JTokenReferenceEqualityComparer : IEqualityComparer<JToken>
{
public static readonly JTokenReferenceEqualityComparer Instance = new JTokenReferenceEqualityComparer();
public bool Equals(JToken x, JToken y)
{
return ReferenceEquals(x, y);
}
public int GetHashCode(JToken obj)
{
if (obj == null)
{
return 0;
}
return obj.GetHashCode();
}
}
internal int IndexOfItem(JToken item)
{
return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
}
internal abstract int IndexOfItem(JToken item);
internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
{
+5
View File
@@ -128,6 +128,11 @@ namespace Newtonsoft.Json.Linq
return _properties.Compare(t._properties);
}
internal override int IndexOfItem(JToken item)
{
return _properties.IndexOfReference(item);
}
internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
// don't add comments to JObject, no name to reference comment by
+5
View File
@@ -235,6 +235,11 @@ namespace Newtonsoft.Json.Linq
throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
}
internal override int IndexOfItem(JToken item)
{
return _content.IndexOf(item);
}
internal override void InsertItem(int index, JToken item, bool skipParentCheck)
{
// don't add comments to JProperty
@@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Newtonsoft.Json.Utilities;
namespace Newtonsoft.Json.Linq
{
@@ -35,6 +36,10 @@ namespace Newtonsoft.Json.Linq
private Dictionary<string, JToken> _dictionary;
public JPropertyKeyedCollection() : base(new List<JToken>())
{
}
private void AddKey(string key, JToken item)
{
EnsureDictionary();
@@ -220,6 +225,11 @@ namespace Newtonsoft.Json.Linq
}
}
public int IndexOfReference(JToken t)
{
return ((List<JToken>)Items).IndexOfReference(t);
}
public bool Compare(JPropertyKeyedCollection other)
{
if (this == other)
+1 -1
View File
@@ -1883,7 +1883,7 @@ namespace Newtonsoft.Json.Linq
/// <returns>An <see cref="JsonReader"/> that can be used to read this token and its descendants.</returns>
public JsonReader CreateReader()
{
return new JTokenReader(this, Path);
return new JTokenReader(this);
}
internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer)
+7 -1
View File
@@ -33,8 +33,8 @@ namespace Newtonsoft.Json.Linq
/// </summary>
public class JTokenReader : JsonReader, IJsonLineInfo
{
private readonly string _initialPath;
private readonly JToken _root;
private string _initialPath;
private JToken _parent;
private JToken _current;
@@ -57,6 +57,7 @@ namespace Newtonsoft.Json.Linq
_root = token;
}
// this is used by json.net schema
internal JTokenReader(JToken token, string initialPath)
: this(token)
{
@@ -306,6 +307,11 @@ namespace Newtonsoft.Json.Linq
{
string path = base.Path;
if (_initialPath == null)
{
_initialPath = _root.Path;
}
if (!string.IsNullOrEmpty(_initialPath))
{
if (string.IsNullOrEmpty(path))
@@ -214,11 +214,11 @@ namespace Newtonsoft.Json.Utilities
return -1;
}
public static bool Contains(this IEnumerable list, object value, IEqualityComparer comparer)
public static bool Contains<T>(this List<T> list, T value, IEqualityComparer comparer)
{
foreach (object item in list)
for (int i = 0; i < list.Count; i++)
{
if (comparer.Equals(item, value))
if (comparer.Equals(value, list[i]))
{
return true;
}
@@ -226,24 +226,14 @@ namespace Newtonsoft.Json.Utilities
return false;
}
/// <summary>
/// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer{TSource}.
/// </summary>
/// <typeparam name="TSource">The type of the elements of source.</typeparam>
/// <param name="list">A sequence in which to locate a value.</param>
/// <param name="value">The object to locate in the sequence</param>
/// <param name="comparer">An equality comparer to compare values.</param>
/// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1.</returns>
public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value, IEqualityComparer<TSource> comparer)
public static int IndexOfReference<T>(this List<T> list, T item)
{
int index = 0;
foreach (TSource item in list)
for (int i = 0; i < list.Count; i++)
{
if (comparer.Equals(item, value))
if (ReferenceEquals(item, list[i]))
{
return index;
return i;
}
index++;
}
return -1;
}