Instantly share code, notes, and snippets.
Created
August 14, 2020 20:20
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save steveharter/f5ba125d3bd72bc599e61a7ac73e86f3 to your computer and use it in GitHub Desktop.
TempCodeShare for converter perf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#define NEW_APIS | |
// writer custom auto | |
// 4 5 12 release | |
// 22 release | |
// Master | |
// 8 13 27 | |
// 8 40 | |
// 22 27 | |
// 48 | |
// Fast but no NEW_APIS | |
// 20 32 | |
// new APIs | |
// 7 4 12 (run all - load reader etc) | |
// 10 9 | |
// 15 (avoid ref emit) | |
using System.Text; | |
using System; | |
using System.IO; | |
using System.Linq; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Text.Json; | |
using System.ComponentModel.Design; | |
using System.ComponentModel.DataAnnotations; | |
using System.Text.Json.Serialization; | |
//using System.Text.Json.Serialization.Converters; | |
using System.Runtime.Intrinsics.X86; | |
namespace Test | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
IEnumerable<WeatherForecast> result = Perf.Get(); | |
// pre-load System.Intrinsics | |
//JsonEncodedText temp = JsonEncodedText.Encode("Hello"); | |
//Perf.Writer(result); // 9 | |
// Perf.Custom(result); // 22 (master compiled) --> 19 (avoiding ngen - meaning as fast as writer with -11) | |
Perf.Auto(result); // 48 (master compiled). Current= 12+1=13 | |
// Using original master (crossgen): 11 (so subtract 11 on current code) | |
// current: 12+10=22 | |
//Console.ReadLine(); | |
} | |
#if NEW_APIS | |
public static class Serializer | |
{ | |
public static JsonSerializerOptions Options { get; } | |
public static DateTimeConverter DateTimeConverter { get; } | |
public static Int32Converter Int32Converter { get; } | |
public static StringConverter StringConverter { get; } | |
static Serializer() | |
{ | |
// Assume these will be on options and no dictionary lookup | |
var sw = new Stopwatch(); | |
sw.Start(); | |
Options = new JsonSerializerOptions(); | |
DateTimeConverter = new DateTimeConverter();// (DateTimeConverter)Options.GetConverter(typeof(DateTime)); | |
Int32Converter = new Int32Converter(); // (Int32Converter)Options.GetConverter(typeof(int)); | |
StringConverter = new StringConverter(); // (StringConverter)Options.GetConverter(typeof(string)); | |
//DateTimeConverter = (DateTimeConverter)Options.GetConverter(typeof(DateTime)); | |
//Int32Converter = (Int32Converter)Options.GetConverter(typeof(int)); | |
//StringConverter = (StringConverter)Options.GetConverter(typeof(string)); | |
sw.Stop(); | |
Console.WriteLine("JsonSerializerOptions " + sw.ElapsedMilliseconds); | |
} | |
} | |
#endif | |
public class WeatherForecast | |
{ | |
#if NEW_APIS | |
static WeatherForecast() | |
{ | |
ClassInfo classInfo = new ClassInfo(Serializer.Options); | |
classInfo.Initialize(); | |
Serializer.Options.Classes.TryAdd(typeof(WeatherForecast), classInfo); | |
} | |
#endif | |
public DateTime Date { get; set; } | |
public int TemperatureC { get; set; } | |
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); | |
public string Summary { get; set; } | |
public string P0_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P1_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P2_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P3_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P4_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P5_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P6_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P7_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P8_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
public string P9_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890_01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 { get; set; } | |
#if NEW_APIS | |
private class ClassInfo : JsonClassInfo | |
{ | |
public ClassInfo(JsonSerializerOptions options) : base(typeof(WeatherForecast), options) | |
{ | |
CreateObject = () => { return new WeatherForecast(); }; | |
} | |
protected override IList<JsonPropertyInfo> GetProperties() | |
{ | |
var p = new JsonPropertyInfo<DateTime>(); | |
p.Options = Options; | |
p.Converter = Serializer.DateTimeConverter; | |
p.NameAsString = nameof(WeatherForecast.Date); | |
var sw = new Stopwatch(); | |
sw.Start(); | |
//var DateTimeConverter = (DateTimeConverter)Options.GetConverter(typeof(DateTime)); | |
//var Int32Converter = (Int32Converter)Options.GetConverter(typeof(int)); | |
//var StringConverter = (StringConverter)Options.GetConverter(typeof(string)); | |
var properties = new List<JsonPropertyInfo>(4); | |
properties.Add(new JsonPropertyInfo<DateTime> | |
{ | |
Options = Options, | |
Converter = Serializer.DateTimeConverter, | |
NameAsString = nameof(WeatherForecast.Date), | |
HasGetter = true, | |
HasSetter = true, | |
ShouldSerialize = true, | |
ShouldDeserialize = true, | |
Get = (obj) => { return ((WeatherForecast)obj).Date; }, | |
Set = (obj, value) => { ((WeatherForecast)obj).Date = value; } | |
}); | |
properties.Add(new JsonPropertyInfo<int> | |
{ | |
Options = Options, | |
Converter = Serializer.Int32Converter, | |
NameAsString = nameof(WeatherForecast.TemperatureC), | |
HasGetter = true, | |
HasSetter = true, | |
Get = (obj) => { return ((WeatherForecast)obj).TemperatureC; }, | |
Set = (obj, value) => { ((WeatherForecast)obj).TemperatureC = value; } | |
}); | |
properties.Add(new JsonPropertyInfo<int> | |
{ | |
Options = Options, | |
Converter = Serializer.Int32Converter, | |
HasGetter = true, | |
NameAsString = nameof(WeatherForecast.TemperatureF), | |
Get = (obj) => { return ((WeatherForecast)obj).TemperatureF; }, | |
}); | |
properties.Add(new JsonPropertyInfo<string> | |
{ | |
Options = Options, | |
Converter = Serializer.StringConverter, | |
NameAsString = nameof(WeatherForecast.Summary), | |
HasGetter = true, | |
HasSetter = true, | |
Get = (obj) => { return ((WeatherForecast)obj).Summary; }, | |
Set = (obj, value) => { ((WeatherForecast)obj).Summary = value; } | |
}); | |
sw.Stop(); | |
Console.WriteLine("ADD Properties " + sw.ElapsedMilliseconds); | |
return properties; | |
} | |
} | |
#endif | |
} | |
public class Perf | |
{ | |
private static readonly string[] Summaries = new[] | |
{ | |
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | |
}; | |
public static IEnumerable<WeatherForecast> Get() | |
{ | |
var result = new WeatherForecast[] | |
{ | |
new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(0), | |
TemperatureC = 0, | |
Summary = Summaries[0] | |
}, | |
new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(1), | |
TemperatureC = 1, | |
Summary = Summaries[1] | |
}, | |
new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(2), | |
TemperatureC = 2, | |
Summary = Summaries[2] | |
}, | |
new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(3), | |
TemperatureC = 3, | |
Summary = Summaries[3] | |
}, | |
new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(4), | |
TemperatureC = 4, | |
Summary = Summaries[4] | |
} | |
}; | |
// var rng = new Random(); | |
//WeatherForecast[] result = Enumerable.Range(1, 5).Select(index => new WeatherForecast | |
//{ | |
// Date = DateTime.Now.AddDays(index), | |
// TemperatureC = rng.Next(-20, 55), | |
// Summary = Summaries[rng.Next(Summaries.Length)] | |
//}) | |
//.ToArray(); | |
return result; | |
} | |
public static void Writer(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
var ms = new MemoryStream(); | |
using (var writer = new Utf8JsonWriter(ms)) | |
{ | |
writer.WriteStartArray(); | |
foreach (var w in result) | |
{ | |
writer.WriteStartObject(); | |
writer.WriteString("Date", w.Date); | |
writer.WriteNumber("TemperatureC", w.TemperatureC); | |
writer.WriteNumber("TemperatureF", w.TemperatureF); | |
writer.WriteString("Summary", w.Summary); | |
writer.WriteEndObject(); | |
} | |
writer.WriteEndArray(); | |
} | |
sw.Stop(); | |
Console.WriteLine("Writer" + sw.ElapsedMilliseconds); | |
} | |
public static void Auto(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
var ms = new MemoryStream(); | |
foreach (var w in result) | |
{ | |
#if NEW_APIS | |
JsonSerializer.SerializeToUtf8Bytes(result, Serializer.Options); | |
//string s = JsonSerializer.Serialize(result, Serializer.Options); | |
#else | |
JsonSerializer.SerializeToUtf8Bytes(result); | |
#endif | |
} | |
sw.Stop(); | |
Console.WriteLine("Auto:" + sw.ElapsedMilliseconds); | |
} | |
public static void Custom(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
var options = new JsonSerializerOptions(); | |
options.Converters.Add(new WeatherForecastConverter()); | |
options.Converters.Add(new IEnumerableWeatherForecastConverter()); | |
var ms = new MemoryStream(); | |
foreach (var w in result) | |
{ | |
JsonSerializer.SerializeToUtf8Bytes(result, options); | |
} | |
sw.Stop(); | |
Console.WriteLine("Custom:" + sw.ElapsedMilliseconds); | |
} | |
public class WeatherForecastConverter : JsonConverter<WeatherForecast> | |
{ | |
public override WeatherForecast Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override void Write(Utf8JsonWriter writer, WeatherForecast value, JsonSerializerOptions options) | |
{ | |
writer.WriteStartObject(); | |
writer.WriteString("Date", value.Date); | |
writer.WriteNumber("TemperatureC", value.TemperatureC); | |
writer.WriteNumber("TemperatureF", value.TemperatureF); | |
writer.WriteString("Summary", value.Summary); | |
writer.WriteEndObject(); | |
} | |
} | |
public class IEnumerableWeatherForecastConverter : JsonConverter<IEnumerable<WeatherForecast>> | |
{ | |
JsonConverter<WeatherForecast> converter = null; | |
public override IEnumerable<WeatherForecast> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override void Write(Utf8JsonWriter writer, IEnumerable<WeatherForecast> value, JsonSerializerOptions options) | |
{ | |
if (converter == null) | |
{ | |
converter = (JsonConverter<WeatherForecast>)options.GetConverter(typeof(WeatherForecast)); | |
} | |
writer.WriteStartArray(); | |
foreach (WeatherForecast element in value) | |
{ | |
converter.Write(writer, element, options); | |
} | |
writer.WriteEndArray(); | |
} | |
} | |
} | |
} | |
} | |
/* | |
[AttributeUsage(AttributeTargets.Class)] | |
public class MyAttrAttribute : Attribute | |
{ | |
public Type MyType { get; set; } = typeof(WeatherForecast); | |
} | |
[MyAttrAttribute] | |
public class WeatherForecast | |
{ | |
public DateTime Date { get; set; } | |
public int TemperatureC { get; set; } | |
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); | |
public string Summary { get; set; } | |
} | |
class Program | |
{ | |
private static readonly string[] Summaries = new[] | |
{ | |
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" | |
}; | |
public static IEnumerable<WeatherForecast> Get() | |
{ | |
var rng = new Random(); | |
return Enumerable.Range(1, 5).Select(index => new WeatherForecast | |
{ | |
Date = DateTime.Now.AddDays(index), | |
TemperatureC = rng.Next(-20, 55), | |
Summary = Summaries[rng.Next(Summaries.Length)] | |
}) | |
.ToArray(); | |
} | |
static void Main(string[] args) | |
{ | |
IEnumerable<WeatherForecast> result = Get(); | |
CustomAttr(result); | |
//JsonSerializerOptions options = new JsonSerializerOptions(); | |
//JsonSerializerOptions options2 = new JsonSerializerOptions(); | |
//JsonSerializer.SerializeToUtf8Bytes(result); // all : 2 once options set | |
//Writer(result); // 9 | |
//Auto(result); // 48 (master compiled) | |
//Custom(result); // 22 (master compiled) --> 19 (avoiding ngen - meaning as fast as writer with -11) | |
// Using original master (crossgen): 11 (so subtract 11 on current code) | |
} | |
static void CustomAttr(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
object[] a = typeof(WeatherForecast).GetCustomAttributes(typeof(MyAttrAttribute), false); | |
if (a.Length > 0) | |
{ | |
Type t = ((MyAttrAttribute)a[0]).MyType; | |
object o = Activator.CreateInstance(t); | |
} | |
sw.Stop(); | |
Console.WriteLine(sw.ElapsedTicks); | |
Console.WriteLine(sw.ElapsedMilliseconds); | |
} | |
static void Writer(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
var ms = new MemoryStream(); | |
using (var writer = new Utf8JsonWriter(ms)) | |
{ | |
writer.WriteStartArray(); | |
foreach (var w in result) | |
{ | |
writer.WriteStartObject(); | |
writer.WriteString("Date", w.Date); | |
writer.WriteNumber("TemperatureC", w.TemperatureC); | |
writer.WriteNumber("TemperatureF", w.TemperatureF); | |
writer.WriteString("Summary", w.Summary); | |
writer.WriteEndObject(); | |
} | |
writer.WriteEndArray(); | |
} | |
sw.Stop(); | |
Console.WriteLine(sw.ElapsedMilliseconds); | |
} | |
static void Auto(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
var ms = new MemoryStream(); | |
foreach (var w in result) | |
{ | |
JsonSerializer.SerializeToUtf8Bytes(result); | |
} | |
sw.Stop(); | |
Console.WriteLine(sw.ElapsedMilliseconds); | |
} | |
static void Custom(IEnumerable<WeatherForecast> result) | |
{ | |
var sw = new Stopwatch(); | |
sw.Start(); | |
// saves 2 when creating before | |
var options = new JsonSerializerOptions(); | |
options.Converters.Add(new WeatherForecastConverter()); | |
options.Converters.Add(new IEnumerableWeatherForecastConverter()); | |
var ms = new MemoryStream(); | |
foreach (var w in result) | |
{ | |
JsonSerializer.SerializeToUtf8Bytes(result, options); | |
} | |
sw.Stop(); | |
//Console.WriteLine(sw.ElapsedMilliseconds); | |
} | |
} | |
public class WeatherForecastConverter : JsonConverter<WeatherForecast> | |
{ | |
public override WeatherForecast Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override void Write(Utf8JsonWriter writer, WeatherForecast value, JsonSerializerOptions options) | |
{ | |
writer.WriteStartObject(); | |
writer.WriteString("Date", value.Date); | |
writer.WriteNumber("TemperatureC", value.TemperatureC); | |
writer.WriteNumber("TemperatureF", value.TemperatureF); | |
writer.WriteString("Summary", value.Summary); | |
writer.WriteEndObject(); | |
} | |
} | |
public class IEnumerableWeatherForecastConverter : JsonConverter<IEnumerable<WeatherForecast>> | |
{ | |
JsonConverter<WeatherForecast> converter = null; | |
public override IEnumerable<WeatherForecast> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) | |
{ | |
throw new NotImplementedException(); | |
} | |
public override void Write(Utf8JsonWriter writer, IEnumerable<WeatherForecast> value, JsonSerializerOptions options) | |
{ | |
if (converter == null) | |
{ | |
converter = (JsonConverter<WeatherForecast>)options.GetConverter(typeof(WeatherForecast)); | |
} | |
writer.WriteStartArray(); | |
foreach (WeatherForecast element in value) | |
{ | |
converter.Write(writer, element, options); | |
} | |
writer.WriteEndArray(); | |
} | |
} | |
//public class POCO : IJsonSerializable | |
//{ | |
// JsonClassInfo IJsonSerializable.GetJsonClassInfo() | |
// { | |
// return new MyJsonClassInfo(this); | |
// } | |
// private class MyJsonClassInfo : JsonClassInfo | |
// { | |
// private POCO _obj; | |
// public MyJsonClassInfo(POCO obj) | |
// { | |
// _obj = obj; | |
// } | |
// public override JsonPropertyInfo[] GetProperties() | |
// { | |
// return new JsonPropertyInfo[] | |
// { | |
// new JsonPropertyInfo<int>( | |
// creator : null, | |
// getter : () => { return _obj.MyIntProp; }, | |
// setter : (value) => { _obj.MyIntProp = value; }) | |
// }; | |
// } | |
// } | |
//public int MyIntProp { get; set; } | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment