-Improved large JArray performance
-Improved JTokenReader performance
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user