.NET JsonSerializer ist über 200-mal schneller, wenn Sie JsonSerializerOptions wiederverwenden

 C Programming >> C-Programmierung >  >> Tags >> .NET
.NET JsonSerializer ist über 200-mal schneller, wenn Sie JsonSerializerOptions wiederverwenden

Wenn Sie ein Objekt mit dem integrierten .NET JsonSerializer (System.Text.Json) serialisieren, ist die Wiederverwendung des JsonSerializerOptions-Objekts 200-mal schneller als die Serialisierung jedes Mal mit einem neuen Optionsobjekt.

Das JsonSerializerOptions-Objekt muss über einen internen Caching-Mechanismus verfügen, der nachfolgende Serialisierungen desselben Typs deutlich schneller macht. Hinweis:Das Erstellen des neuen JsonSerializerOptions-Objekts erhöht die Gesamtkosten der Serialisierung nur unwesentlich. Das habe ich beim Vergleich der Serialisierungsgeschwindigkeiten berücksichtigt. Selbst wenn Sie die Zeit außer Acht lassen, die für die Neuerstellung des Objekts benötigt wird, ist die Wiederverwendung des Optionsobjekts bei nachfolgenden Serialisierungen immer noch 200-mal schneller.

In diesem Artikel zeige ich einen Geschwindigkeitsvergleich der Serialisierung mit und ohne Wiederverwendung von JsonSerializerOptions.

Geschwindigkeitsvergleichsergebnisse – Wiederverwendung vs. Nicht-Wiederverwendung von JsonSerializerOptions

Um die Geschwindigkeiten zu vergleichen, habe ich dasselbe Objekt 100 Mal in einer Schleife serialisiert und dann den Durchschnitt, das Minimum, das Maximum, das erste Mal und den Durchschnitt ohne das erste Mal genommen.

Sie denken vielleicht, dass die Neuerstellung des JsonSerializerOptions-Objekts der Grund für den Wiederverwendungsansatz sein könnte ist so viel schneller, aber das ist nicht der Fall. Das fügt im Durchschnitt 0,02 ms hinzu, was praktisch keinen Einfluss auf die Gesamtzeit hat, die für die Serialisierung benötigt wird.

Die erstmalige Serialisierung eines Objekts ist immer langsam. Deshalb vergleiche ich die durchschnittliche Zeit ohne zuerst Serialisierung .

Geschwindigkeitsvergleichstabelle:

Durchschnittliche Zeit ohne erste Serialisierung
Ansatz 1 – JsonSerializerOptions nicht wiederverwenden Optionsobjekt erstellen:0,0221 ms
Serialisierung:3,043 ms
Gesamt:3,0651 ms
Ansatz 2 – Wiederverwendung von JsonSerializerOptions 0,0145 ms

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

Ansatz 2 – Wiederverwendung der JsonSerializerOptions – ist 211x schneller als die Optionen nicht wiederzuverwenden.

Ich würde spekulieren, dass JsonSerializerOptions einen internen Caching-Mechanismus enthält, der nachfolgende Serialisierungen desselben Typs erheblich schneller macht. Aber wie es funktioniert, ist nicht so wichtig. Wenn Sie wiederholt Serialisierungen durchführen, verwenden Sie das Optionsobjekt immer wieder.

Ansatz 1 – Geschwindigkeitstest – Serialisieren und KEINE Wiederverwendung von JsonSerializerOptions

  • unter Verwendung von 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)

Erstellen des Optionsobjekts:

  • Min.=0,0024 ms
  • Max=1,8253 ms
  • Durchschn.=0,0221 ms

Serialisierung:

  • Erste=43,0357 ms
  • Min.=2,4857 ms
  • Max=43,036 ms
  • Durchschn.=3,4436 ms
  • AvgWithoutFirst=3,043 ms

Gesamtdurchschnitt (Neues Optionsobjekt erstellen + Serialisieren) ohne erste:0,0221 ms + 3,043 ms =3,0651 ms

Ansatz 2 – Geschwindigkeitstest – Serialisieren und Wiederverwenden von JsonSerializerOptions

  • unter Verwendung von 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)

Serialisierung:

  • Erste=45,39 ms
  • Min.=0,0107 ms
  • Max =45,39 ms
  • Durchschn. =0,4678 ms
  • Durchschnitt ohne erste =0,0145 ms

NFLTeam – Objekt, das für Serialisierungstests verwendet wird

{
	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)