Skip to content

Instantly share code, notes, and snippets.

@steveharter
Created August 14, 2020 20:20
Show Gist options
  • Save steveharter/f5ba125d3bd72bc599e61a7ac73e86f3 to your computer and use it in GitHub Desktop.
Save steveharter/f5ba125d3bd72bc599e61a7ac73e86f3 to your computer and use it in GitHub Desktop.
TempCodeShare for converter perf
//#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