Skip to content

Commit

Permalink
Extend source generator tests as a mode in the main JsonSerializer be…
Browse files Browse the repository at this point in the history
…nchmarks.
  • Loading branch information
eiriktsarpalis committed Nov 18, 2022
1 parent da3e388 commit 45e6a44
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 43 deletions.
74 changes: 50 additions & 24 deletions src/benchmarks/micro/Serializers/DataGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.Json;
#if NET6_0_OR_GREATER
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
Expand All @@ -19,7 +20,7 @@

namespace MicroBenchmarks.Serializers
{
internal static partial class DataGenerator
internal static class DataGenerator
{
internal static T Generate<T>()
{
Expand Down Expand Up @@ -220,32 +221,19 @@ private static XmlElement CreateXmlElement()
return xmlElement;
}

internal static JsonSerializerOptions GetJsonSerializerOptions(SystemTextJsonSerializationMode mode)
=> mode switch
{
SystemTextJsonSerializationMode.Reflection => new JsonSerializerOptions(),
#if NET6_0_OR_GREATER
SystemTextJsonSerializationMode.SourceGen => SystemTextJsonSourceGeneratedContext.Default.Options,
#endif
_ => throw new NotSupportedException(mode.ToString())
};

#if NET6_0_OR_GREATER
internal static JsonTypeInfo<T> GetSystemTextJsonSourceGenMetadata<T>()
=> (JsonTypeInfo<T>)SystemTextJsonSourceGeneratedContext.Default.GetTypeInfo(typeof(T));

[JsonSerializable(typeof(LoginViewModel))]
[JsonSerializable(typeof(Location))]
[JsonSerializable(typeof(IndexViewModel))]
[JsonSerializable(typeof(MyEventsListerViewModel))]
[JsonSerializable(typeof(BinaryData))]
[JsonSerializable(typeof(CollectionsOfPrimitives))]
[JsonSerializable(typeof(XmlElement))]
[JsonSerializable(typeof(SimpleStructWithProperties))]
[JsonSerializable(typeof(SimpleListOfInt))]
[JsonSerializable(typeof(ClassImplementingIXmlSerialiable))]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(ImmutableDictionary<string, string>))]
[JsonSerializable(typeof(ImmutableSortedDictionary<string, string>))]
[JsonSerializable(typeof(HashSet<string>))]
[JsonSerializable(typeof(ArrayList))]
[JsonSerializable(typeof(Hashtable))]
[JsonSerializable(typeof(LargeStructWithProperties))]
[JsonSerializable(typeof(DateTimeOffset?))]
[JsonSerializable(typeof(int))]
private partial class SystemTextJsonSourceGeneratedContext : JsonSerializerContext
{
}
#endif
}

Expand Down Expand Up @@ -453,4 +441,42 @@ public void WriteXml(XmlWriter writer)
writer.WriteAttributeString("BoolValue", BoolValue.ToString());
}
}

public class ClassWithObjectProperty
{
public object Prop { get; set; }
}

public enum SystemTextJsonSerializationMode
{
Reflection = 0,
SourceGen = 1
}

#if NET6_0_OR_GREATER
[JsonSerializable(typeof(ClassWithObjectProperty))]
[JsonSerializable(typeof(LoginViewModel))]
[JsonSerializable(typeof(Location))]
[JsonSerializable(typeof(IndexViewModel))]
[JsonSerializable(typeof(MyEventsListerViewModel))]
[JsonSerializable(typeof(BinaryData))]
[JsonSerializable(typeof(CollectionsOfPrimitives))]
[JsonSerializable(typeof(XmlElement))]
[JsonSerializable(typeof(SimpleStructWithProperties))]
[JsonSerializable(typeof(SimpleListOfInt))]
[JsonSerializable(typeof(ClassImplementingIXmlSerialiable))]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(ImmutableDictionary<string, string>))]
[JsonSerializable(typeof(ImmutableSortedDictionary<string, string>))]
[JsonSerializable(typeof(HashSet<string>))]
[JsonSerializable(typeof(ArrayList))]
[JsonSerializable(typeof(Hashtable))]
[JsonSerializable(typeof(LargeStructWithProperties))]
[JsonSerializable(typeof(DateTimeOffset?))]
[JsonSerializable(typeof(int))]
[JsonSerializable(typeof(object))]
internal partial class SystemTextJsonSourceGeneratedContext : JsonSerializerContext
{
}
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ private T RoundtripSerialization(JsonSerializerOptions options)
[Benchmark]
public T NewDefaultOptions() => RoundtripSerialization(new JsonSerializerOptions());

#if NET6_0_OR_GREATER
[Benchmark]
public T CachedJsonSerializerContext()
=> RoundtripSerialization(SystemTextJsonSourceGeneratedContext.Default.Options);

[Benchmark]
public T NewJsonSerializerContext()
{
var options = new JsonSerializerOptions();
options.AddContext<SystemTextJsonSourceGeneratedContext>();
return RoundtripSerialization(options);
}
#endif

[Benchmark]
public T NewCustomizedOptions() =>
RoundtripSerialization(
Expand All @@ -61,11 +75,11 @@ public T NewCustomConverter() =>

[Benchmark]
public T NewCachedCustomConverter() =>
RoundtripSerialization(
new JsonSerializerOptions
{
WriteIndented = true,
Converters = { _converter }
});
RoundtripSerialization(
new JsonSerializerOptions
{
WriteIndented = true,
Converters = { _converter }
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ namespace System.Text.Json.Serialization.Tests
[AotFilter("Currently not supported due to missing metadata.")]
public class ReadJson<T>
{
#if NET6_0_OR_GREATER
[Params(SystemTextJsonSerializationMode.Reflection, SystemTextJsonSerializationMode.SourceGen)]
#else
[Params(SystemTextJsonSerializationMode.Reflection)]
#endif
public SystemTextJsonSerializationMode Mode;

private JsonSerializerOptions _options;
private string _serialized;
private byte[] _utf8Serialized;
private MemoryStream _memoryStream;
Expand All @@ -40,37 +48,38 @@ public class ReadJson<T>
public async Task Setup()
{
T value = DataGenerator.Generate<T>();
_options = DataGenerator.GetJsonSerializerOptions(Mode);

_serialized = JsonSerializer.Serialize(value);
_serialized = JsonSerializer.Serialize(value, _options);

_utf8Serialized = Encoding.UTF8.GetBytes(_serialized);

_memoryStream = new MemoryStream(capacity: short.MaxValue);
await JsonSerializer.SerializeAsync(_memoryStream, value);
await JsonSerializer.SerializeAsync(_memoryStream, value, _options);
}

[BenchmarkCategory(Categories.Libraries, Categories.JSON)]
[Benchmark]
public T DeserializeFromString() => JsonSerializer.Deserialize<T>(_serialized);
public T DeserializeFromString() => JsonSerializer.Deserialize<T>(_serialized, _options);

[BenchmarkCategory(Categories.Libraries, Categories.JSON)]
[Benchmark]
public T DeserializeFromUtf8Bytes() => JsonSerializer.Deserialize<T>(_utf8Serialized);
public T DeserializeFromUtf8Bytes() => JsonSerializer.Deserialize<T>(_utf8Serialized, _options);

[BenchmarkCategory(Categories.Libraries, Categories.JSON)]
[Benchmark]
public T DeserializeFromReader()
{
Utf8JsonReader reader = new Utf8JsonReader(_utf8Serialized);
return JsonSerializer.Deserialize<T>(ref reader);
return JsonSerializer.Deserialize<T>(ref reader, _options);
}

[BenchmarkCategory(Categories.Libraries, Categories.JSON, Categories.NoWASM)]
[Benchmark]
public async Task<T> DeserializeFromStream()
{
_memoryStream.Position = 0;
T value = await JsonSerializer.DeserializeAsync<T>(_memoryStream);
T value = await JsonSerializer.DeserializeAsync<T>(_memoryStream, _options);
return value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ namespace System.Text.Json.Serialization.Tests
[AotFilter("Currently not supported due to missing metadata.")]
public class WriteJson<T>
{
#if NET6_0_OR_GREATER
[Params(SystemTextJsonSerializationMode.Reflection, SystemTextJsonSerializationMode.SourceGen)]
#else
[Params(SystemTextJsonSerializationMode.Reflection)]
#endif
public SystemTextJsonSerializationMode Mode;

private JsonSerializerOptions _options;
private T _value;
private MemoryStream _memoryStream;
private object _objectWithObjectProperty;
Expand All @@ -45,11 +53,12 @@ public class WriteJson<T>
public async Task Setup()
{
_value = DataGenerator.Generate<T>();
_options = DataGenerator.GetJsonSerializerOptions(Mode);

_memoryStream = new MemoryStream(capacity: short.MaxValue);
await JsonSerializer.SerializeAsync(_memoryStream, _value);
await JsonSerializer.SerializeAsync(_memoryStream, _value, _options);

_objectWithObjectProperty = new { Prop = (object)_value };
_objectWithObjectProperty = new ClassWithObjectProperty { Prop = (object)_value };

_bufferWriter = new ArrayBufferWriter();
_writer = new Utf8JsonWriter(_bufferWriter);
Expand All @@ -59,15 +68,15 @@ public async Task Setup()
public void Cleanup() => _memoryStream.Dispose();

[Benchmark]
public string SerializeToString() => JsonSerializer.Serialize(_value);
public string SerializeToString() => JsonSerializer.Serialize(_value, _options);

[Benchmark]
public byte[] SerializeToUtf8Bytes() => JsonSerializer.SerializeToUtf8Bytes(_value);
public byte[] SerializeToUtf8Bytes() => JsonSerializer.SerializeToUtf8Bytes(_value, _options);

[Benchmark]
public void SerializeToWriter()
{
JsonSerializer.Serialize(_writer, _value);
JsonSerializer.Serialize(_writer, _value, _options);
_bufferWriter.Reset();
_writer.Reset();
}
Expand All @@ -77,11 +86,11 @@ public void SerializeToWriter()
public async Task SerializeToStream()
{
_memoryStream.Position = 0;
await JsonSerializer.SerializeAsync(_memoryStream, _value);
await JsonSerializer.SerializeAsync(_memoryStream, _value, _options);
}

[Benchmark]
public string SerializeObjectProperty() => JsonSerializer.Serialize(_objectWithObjectProperty);
public string SerializeObjectProperty() => JsonSerializer.Serialize(_objectWithObjectProperty, _options);

private sealed class ArrayBufferWriter : IBufferWriter<byte>
{
Expand Down

0 comments on commit 45e6a44

Please sign in to comment.