Skip to content

Commit

Permalink
add resolver, formatters tests, update benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
Fausto David committed Feb 18, 2020
1 parent 9609b7e commit 57eb9b6
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 100 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@
/tests/ListPool.Resolvers.Utf8Json.Tests/bin/Debug/netcoreapp3.1
/src/ListPool.Resolvers.Utf8Json/obj
/src/ListPool.Resolvers.Utf8Json/bin/Debug/netstandard2.0
/src/ListPool.Resolvers.Utf8Json/bin
/tests/ListPool.Resolvers.Utf8Json.Tests/bin/Release/netcoreapp3.1
3 changes: 1 addition & 2 deletions perf/ListPool.Benchmarks/ListPool.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.0" />
<PackageReference Include="Spreads.Core" Version="2020.0.114" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ListPool.Resolvers.Utf8Json\ListPool.Resolvers.Utf8Json.csproj" />
<ProjectReference Include="..\..\src\ListPool\ListPool.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ namespace ListPool.Benchmarks
[GcConcurrent]
public class ListPoolCreateAndAddAndEnumerateAReferenceBenchmarks
{
private static readonly string _stringToAdd = Guid.NewGuid().ToString();

[Params(48, 1_024, 10_240)]
public int N { get; set; }

private static readonly string _stringToAdd = Guid.NewGuid().ToString();

[Benchmark(Baseline = true)]
public int List()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ namespace ListPool.Benchmarks
[GcConcurrent]
public class ListPoolCreateAndAddAndEnumerateAReferenceWithoutIndicateCapacityBenchmarks
{
private static readonly string _stringToAdd = Guid.NewGuid().ToString();

[Params(48, 1_024, 10_240)]
public int N { get; set; }

private static readonly string _stringToAdd = Guid.NewGuid().ToString();

[Benchmark(Baseline = true)]
public int List()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public int ValueListPool()
? new ValueListPool<int>(stackalloc int[N], ValueListPool<int>.SourceType.UseAsInitialBuffer)
: new ValueListPool<int>(N);

for (int i = 0; i < N; i += 8)
for (int i = 0; i < N; i += 8)
{
list.Add(i);
list.Add(i);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public int ValueListPool()
int count = 0;
using ValueListPool<int> list = new ValueListPool<int>(0);

for (int i = 0; i < N; i += 8)
for (int i = 0; i < N; i += 8)
{
list.Add(i);
list.Add(i);
Expand Down
33 changes: 16 additions & 17 deletions perf/ListPool.Benchmarks/Utf8JsonDeserializeListOfIntBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
using Utf8Json;

namespace ListPool.Benchmarks
{
Expand All @@ -21,36 +20,36 @@ public class Utf8JsonDeserializeListOfIntBenchmarks
[GlobalSetup]
public void GlobalSetup()
{
_serializedList = JsonSerializer.Serialize(Enumerable.Range(0, N));
_serializedList = Utf8Json.JsonSerializer.Serialize(Enumerable.Range(0, N));
}

[Benchmark(Baseline = true)]
public int List()
{
List<int> list = JsonSerializer.Deserialize<List<int>>(_serializedList);
List<int> list = Utf8Json.JsonSerializer.Deserialize<List<int>>(_serializedList);
return list.Count;
}

[Benchmark]
public int ListPool()
{
using ListPool<int> list = JsonSerializer.Deserialize<ListPool<int>>(_serializedList);
using ListPool<int> list = Utf8Json.JsonSerializer.Deserialize<ListPool<int>>(_serializedList);
return list.Count;
}

[Benchmark]
public int ListPool_Spreads()
{
using ListPool<int> list =
Spreads.Serialization.Utf8Json.JsonSerializer.Deserialize<ListPool<int>>(_serializedList);
return list.Count;
}
//[Benchmark]
//public int ListPool_Spreads()
//{
// using ListPool<int> list =
// Spreads.Serialization.Utf8Json.JsonSerializer.Deserialize<ListPool<int>>(_serializedList);
// return list.Count;
//}

[Benchmark]
public int List_Spreads()
{
List<int> list = Spreads.Serialization.Utf8Json.JsonSerializer.Deserialize<List<int>>(_serializedList);
return list.Count;
}
//[Benchmark]
//public int List_Spreads()
//{
// List<int> list = Spreads.Serialization.Utf8Json.JsonSerializer.Deserialize<List<int>>(_serializedList);
// return list.Count;
//}
}
}
45 changes: 32 additions & 13 deletions perf/ListPool.Benchmarks/Utf8JsonSerializeListOfIntBenchmarks.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
using ListPool.Resolvers.Utf8Json;
using Utf8Json;

namespace ListPool.Benchmarks
Expand All @@ -13,10 +15,11 @@ namespace ListPool.Benchmarks
[GcConcurrent]
public class Utf8JsonSerializeListOfIntBenchmarks
{
private readonly ListPoolResolver _resolver = new ListPoolResolver();
private List<int> _list;
private ListPool<int> _listPool;

[Params(100, 1_000, 10_000)]
[Params(1_000)]
public int N { get; set; }

[GlobalSetup]
Expand All @@ -33,26 +36,42 @@ public void GlobalCleanup()
_listPool.Dispose();
}

[Benchmark(Baseline = true)]
[Benchmark]
public int List()
{
byte[] serializedItems = JsonSerializer.Serialize(_list);
return serializedItems.Length;
int count = 0;
List<int> list = _list;

count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;
count += JsonSerializer.Serialize(list).Length;

return count;
}


[Benchmark]
public int ListPool()
{
byte[] serializedItems = JsonSerializer.Serialize(_listPool);
return serializedItems.Length;
}
int count = 0;
ListPoolResolver resolver = _resolver;
ListPool<int> list = _listPool;

count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;
count += JsonSerializer.Serialize(list, resolver).Length;

[Benchmark]
public int ListPool_Spreads()
{
byte[] serializedItems = Spreads.Serialization.Utf8Json.JsonSerializer.Serialize(_listPool);
return serializedItems.Length;
return count;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
<Authors>Fausto David Suarez Rosario</Authors>
<Title>ListPool.Resolvers.Utf8Json</Title>
<AssemblyName>ListPool.Resolvers.Utf8Json</AssemblyName>
<PackageId>ListPool.Resolvers.Utf8Json</PackageId>
<Description>
This library has the resolver and formatter for ListPool to get the maximum performance when serializing objects type ListPool.
</Description>
<PackageTags>ASP.NET;List;System.Buffers;ArrayPool;ListPool;Performance;Span;Utf8Json</PackageTags>
<RepositoryUrl>https://github.com/faustodavid/ListPool</RepositoryUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageVersion>0.1-preview1</PackageVersion>
<PackageReleaseNotes>
Changelog:
* Resolvers and Formatters for ListPool.
</PackageReleaseNotes>
<Copyright>Copyright © Fausto David Suarez Rosario 2020</Copyright>
</PropertyGroup>

<ItemGroup>
Expand Down
53 changes: 15 additions & 38 deletions src/ListPool.Resolvers.Utf8Json/ListPoolFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,71 +1,48 @@
using System;
using System.Runtime.CompilerServices;
using Utf8Json;
using Utf8Json.Resolvers;
using Utf8Json;

namespace ListPool.Resolvers.Utf8Json
{
public class ListPoolFormatter<T> : IJsonFormatter<ListPool<T>>
{
public void Serialize(ref JsonWriter writer, ListPool<T> values, IJsonFormatterResolver formatterResolver)
public void Serialize(ref JsonWriter writer, ListPool<T> value, IJsonFormatterResolver formatterResolver)
{
if (values == null)
if (value == null)
{
writer.WriteNull();
return;
}

writer.WriteBeginArray();
var formatter = formatterResolver.GetFormatterWithVerify<T>();

ReadOnlySpan<T> buffer = values.AsSpan();
IJsonFormatter<T> formatter = formatterResolver.GetFormatterWithVerify<T>();

foreach (T item in buffer)
if (value.Count != 0)
{
formatter.Serialize(ref writer, item, formatterResolver);
writer.WriteValueSeparator();
formatter.Serialize(ref writer, value[0], formatterResolver);
}

writer.GetBuffer().AsSpan()[writer.CurrentOffset - 1] = (byte)']';
}

public ListPool<T> Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
{
int count = 0;
var formatter = formatterResolver.GetFormatterWithVerify<T>();

var list = new ListPool<T>();
reader.ReadIsBeginArrayWithVerify();
while (!reader.ReadIsEndArrayWithSkipValueSeparator(ref count))
foreach (var item in value.AsSpan().Slice(1))
{
list.Add(formatter.Deserialize(ref reader, formatterResolver));
writer.WriteValueSeparator();
formatter.Serialize(ref writer, item, formatterResolver);
}

return list;
writer.WriteEndArray();
}

public ListPool<T> Deserialize(byte[] bytes)
public ListPool<T> Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
{
JsonReader reader = new JsonReader(bytes);
int count = 0;
var formatter = StandardResolver.Default.GetFormatterWithVerify<T>();
var formatter = formatterResolver.GetFormatterWithVerify<T>();

var list = new ListPool<T>();
ListPool<T> listPool = new ListPool<T>();
reader.ReadIsBeginArrayWithVerify();
while (!reader.ReadIsEndArrayWithSkipValueSeparator(ref count))
{
list.Add(formatter.Deserialize(ref reader, StandardResolver.Default));
listPool.Add(formatter.Deserialize(ref reader, formatterResolver));
}

return list;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] Serialize(ListPool<T> listPool)
{
JsonWriter writer = new JsonWriter(MemoryPool.GetBuffer());
Serialize(ref writer, listPool, StandardResolver.Default);
return writer.ToUtf8ByteArray();
return listPool;
}
}
}
25 changes: 25 additions & 0 deletions src/ListPool.Resolvers.Utf8Json/ListPoolResolver.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
using System;
using System.Collections.Generic;
using Utf8Json;
using Utf8Json.Resolvers;

namespace ListPool.Resolvers.Utf8Json
{
public class ListPoolResolver : IJsonFormatterResolver
{
private static readonly Dictionary<Type, object> _formatterMap = new Dictionary<Type, object>(14)
{
// well known collections
{typeof(ListPool<Int16>), new ListPoolFormatter<Int16>()},
{typeof(ListPool<Int32>), new ListPoolFormatter<Int32>()},
{typeof(ListPool<Int64>), new ListPoolFormatter<Int64>()},
{typeof(ListPool<UInt16>), new ListPoolFormatter<UInt16>()},
{typeof(ListPool<UInt32>), new ListPoolFormatter<UInt32>()},
{typeof(ListPool<UInt64>), new ListPoolFormatter<UInt64>()},
{typeof(ListPool<Single>), new ListPoolFormatter<Single>()},
{typeof(ListPool<Double>), new ListPoolFormatter<Double>()},
{typeof(ListPool<Boolean>), new ListPoolFormatter<Boolean>()},
{typeof(ListPool<byte>), new ListPoolFormatter<byte>()},
{typeof(ListPool<SByte>), new ListPoolFormatter<SByte>()},
{typeof(ListPool<DateTime>), new ListPoolFormatter<DateTime>()},
{typeof(ListPool<Char>), new ListPoolFormatter<Char>()},
{typeof(ListPool<string>), new ListPoolFormatter<string>()}
};
public IJsonFormatter<T> GetFormatter<T>()
{
var ti = typeof(T);

if (ti.IsGenericType)
{
if (_formatterMap.TryGetValue(ti, out object formatter))
{
return (IJsonFormatter<T>)formatter;
}

var genericType = ti.GetGenericTypeDefinition();

if (genericType == typeof(ListPool<>))
Expand Down
12 changes: 0 additions & 12 deletions src/ListPool.Resolvers.Utf8Json/MemoryPool.cs

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ListPool.Resolvers.Utf8Json.Tests/CustomObject.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ListPool.Formatters.Utf8Json.Tests
namespace ListPool.Resolvers.Utf8Json.Tests
{
public class CustomObject
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace ListPool.Formatters.Utf8Json.Tests
namespace ListPool.Resolvers.Utf8Json.Tests
{
public sealed class CustomObjectWithListPool : CustomObject, IDisposable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.11.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
<PackageReference Include="Utf8Json" Version="1.3.7" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.0.1" />
Expand Down
Loading

0 comments on commit 57eb9b6

Please sign in to comment.