.NET JsonSerializer es más de 200 veces más rápido si reutiliza JsonSerializerOptions

 C Programming >> Programación C >  >> Tags >> .NET
.NET JsonSerializer es más de 200 veces más rápido si reutiliza JsonSerializerOptions

Cuando serializa un objeto utilizando el JsonSerializer integrado de .NET (System.Text.Json), reutilizar el objeto JsonSerializerOptions es 200 veces más rápido que serializar con un nuevo objeto de opciones cada vez.

El objeto JsonSerializerOptions debe tener algún tipo de mecanismo de almacenamiento en caché interno que haga que las serializaciones posteriores del mismo tipo sean significativamente más rápidas. Nota:La creación del nuevo objeto JsonSerializerOptions agrega un tiempo insignificante al costo total de la serialización. Lo tuve en cuenta al comparar las velocidades de serialización. Incluso si no tiene en cuenta el tiempo que se tarda en actualizar el objeto, la reutilización del objeto de opciones sigue siendo 200 veces más rápida en serializaciones posteriores.

En este artículo, mostraré una comparación de velocidad de serialización con y sin reutilización de JsonSerializerOptions.

Resultados de la comparación de velocidad:reutilización frente a no reutilización de JsonSerializerOptions

Para comparar velocidades, serialicé el mismo objeto 100 veces en un ciclo, luego tomé el promedio, el mínimo, el máximo, la primera vez y el promedio sin la primera vez.

Puede pensar que actualizar el objeto JsonSerializerOptions podría ser la razón por la cual el enfoque de reutilización es mucho más rápido, pero ese no es el caso. Eso agrega, en promedio, 0,02 ms, lo que prácticamente no tiene impacto en el tiempo total que se tarda en serializar.

La serialización de un objeto por primera vez siempre es lenta. Por eso estoy comparando el tiempo promedio sin primero serialización .

Tabla de comparación de velocidades:

Tiempo promedio sin primera serialización
Método 1:no reutilizar JsonSerializerOptions Objeto de opciones de creación:0,0221 ms
Serialización:3,043 ms
Total:3,0651 ms
Enfoque 2:reutilización de JsonSerializerOptions 0,0145 ms

3,0651 ms / 0,0145 ms =211.

El enfoque 2 (reutilizar JsonSerializerOptions) es 211 veces más rápido que no reutilizar las opciones.

Especularía que JsonSerializerOptions contiene algún mecanismo de almacenamiento en caché interno que hace que las serializaciones posteriores del mismo tipo sean significativamente más rápidas. Pero cómo funciona no importa tanto. Si está realizando serializaciones repetidas, siempre reutilice el objeto de opciones.

Método 1:prueba de velocidad:serialización y NO reutilización de JsonSerializerOptions

  • utilizando System.Text.Json;
List<double> nonCachingOptionTimes = new List<double>();
List<double> timeForCreatingNewOptions = new List<double>();
Stopwatch sw = new Stopwatch();

for (int i = 0; i < 100; i++)
{
	sw.Restart();
	var options = new JsonSerializerOptions() { WriteIndented = true };
	options.Converters.Add(new JsonStringEnumConverter());
	timeForCreatingNewOptions.Add(sw.Elapsed.TotalMilliseconds);
	
	sw.Restart();
	var json = JsonSerializer.Serialize(nflTeam, options);
	sw.Stop();
	nonCachingOptionTimes.Add(sw.Elapsed.TotalMilliseconds);
}

Console.WriteLine($"no caching - newing up options. min={timeForCreatingNewOptions.Min()} max={timeForCreatingNewOptions.Max()} avg={timeForCreatingNewOptions.Average()}");
Console.WriteLine($"no caching - serializing. first={nonCachingOptionTimes.First()} min={nonCachingOptionTimes.Min()} max={nonCachingOptionTimes.Max()} avg={nonCachingOptionTimes.Average()} avgWithoutFirst={nonCachingOptionTimes.Skip(1).Average()}");
Code language: C# (cs)

Creando el objeto de opciones:

  • Min =0,0024 ms
  • Máx.=1,8253 ms
  • Promedio=0,0221 ms

Serializando:

  • Primero=43,0357 ms
  • Min =2,4857 ms
  • Máx.=43,036 ms
  • Promedio=3,4436 ms
  • AvgWithoutFirst=3.043 ms

Promedio total (creación de nuevo objeto de opciones + serialización) sin primero:0,0221 ms + 3,043 ms =3,0651 ms

Enfoque 2:prueba de velocidad:serialización y reutilización de JsonSerializerOptions

  • utilizando System.Text.Json;
var cachedOption = new JsonSerializerOptions() { WriteIndented = true };
cachedOption.Converters.Add(new JsonStringEnumConverter());
List<double> cachedOptionTimes = new List<double>();
Stopwatch sw = new Stopwatch();

for (int i = 0; i < 100; i++)
{
	sw.Restart();
	var json = JsonSerializer.Serialize(nflTeam, cachedOption);
	sw.Stop();
	cachedOptionTimes.Add(sw.Elapsed.TotalMilliseconds);
}

Console.WriteLine($"caching. first={cachedOptionTimes.First()} min={cachedOptionTimes.Min()} max={cachedOptionTimes.Max()} avg={cachedOptionTimes.Average()}  avgWithoutFirst={cachedOptionTimes.Skip(1).Average()}");
Code language: C# (cs)

Serializando:

  • Primero=45,39 ms
  • Min =0,0107 ms
  • Máx =45,39 ms
  • Promedio =0,4678 ms
  • Promedio sin primero =0,0145 ms

NFLTeam:objeto utilizado para pruebas de serialización

{
	var team = new NFLTeam()
	{
		City = "Detroit",
		Name = "Lions",
		Conference = Conferences.NFC,
		Divison = Divisions.North,
		HeadCoach = new Person()
		{
			FirstName = "Matt",
			LastName = "Patricia"
		},
		Stats = new Stats()
		{
			RegularSeasonWins = 559,
			RegularSeasonLosses = 658,
			RegularSeasonTies = 32,
			PlayoffWins = 7,
			PlayoffLosses = 13,
			SuperBowlWins = 0,
			SuperBowlLosses = 0
		},
		Players = new List<Player>()
		{
			new Player()
			{
				FirstName = "Matthew",
				LastName = "Stafford",
				Position = PlayerPositions.QB,
				YearsOfExperience = 12,
				College = "Georgia"
			},
			new Player()
			{
				FirstName = "Kenny",
				LastName = "Golladay",
				Position = PlayerPositions.WR,
				YearsOfExperience = 4,
				College = "Northern Illinois"
			},
			new Player()
			{
				FirstName = "Tracy",
				LastName = "Walker",
				Position = PlayerPositions.DB,
				YearsOfExperience = 3,
				College = "Louisiana-Lafayette"
			},
			new Player()
			{
				FirstName = "T.J.",
				LastName = "Hockenson",
				Position = PlayerPositions.TE,
				YearsOfExperience = 2,
				College = "Iowa"
			}
		}
	};
	return team;
}
Code language: C# (cs)