Neu in .NET 8.0 [13]: Leistung von FrozenSet
Eine Menge des Typs FrozenSet gewinnt beim tausendmaligen Aufruf von Contains() gegenüber anderen Objektmengen.
Im vorherigen Teil dieser Serie [1] habe ich die Klasse FrozenSet<T>
im Namensraum System.Collections.Frozen
vorgestellt, die neu in .NET 8.0 ist. Es stellt sich die Frage, warum denn Microsoft FrozentSet<T>
zusätzlich eingeführt hat. Die Antwort der Frage ist – wie so oft – Performance.
Diesmal bewerte ich anhand eines typischen Einsatzbeispiels die Geschwindigkeit.
Gegeben sei eine unsortierte Menge der Zahlen zwischen 1 und 10.000. Wie schnell kann man eine einzelne Zahl in der Menge finden?
Für die Leistungsmessung kommt die Bibliothek BenchmarkDotNet von Microsoft [2] zum Einsatz.
using System.Collections.Frozen;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Toolchains.InProcess.NoEmit;
namespace NET8_Console.Collections_Benchmark;
public class AntiVirusFriendlyConfig : ManualConfig
{
public AntiVirusFriendlyConfig()
{
AddJob(Job.MediumRun
.WithToolchain(InProcessNoEmitToolchain.Instance));
}
}
[Config(typeof(AntiVirusFriendlyConfig))]
public class Collections_Contains_Benchmark
{
private const int Iterations = 1000;
private readonly List<int> list;
private readonly ReadOnlyCollection<int> roCollection;
private readonly FrozenSet<int> frozenSet;
private readonly HashSet<int> hashSet;
private readonly ImmutableList<int> immutableList;
private readonly ImmutableHashSet<int> immutableHashSet;
public Collections_Contains_Benchmark()
{
var array = Enumerable.Range(1, 10000).ToArray();
Random.Shared.Shuffle<int>(array);
list = array.ToList();
// liefert ReadOnlyCollection<T>:
roCollection = list.AsReadOnly();
frozenSet = list.ToFrozenSet();
hashSet = list.ToHashSet();
immutableList = list.ToImmutableList();
immutableHashSet = list.ToImmutableHashSet();
}
[Benchmark(Baseline = true)]
public void ListContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = list.Contains(i);
}
}
[Benchmark]
public void ReadOnlyCollectionContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = roCollection.Contains(i);
}
}
[Benchmark]
public void FrozenSetContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = frozenSet.Contains(i);
}
}
[Benchmark]
public void HashSetContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = hashSet.Contains(i);
}
}
[Benchmark]
public void ImmutableListContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = immutableList.Contains(i);
}
}
[Benchmark]
public void ImmutableHashSetContains()
{
for (var i = 0; i < Iterations; i++)
{
var b = immutableHashSet.Contains(i);
}
}
}
Der in der folgenden Abbildung dargestellte Benchmark ruft 1000-mal die Methode Contains()
auf einer unsortierten Liste mit 10.000 Zahlen auf. Die Menge des Typs FrozenSet
gewinnt beim 1000-maligen Aufruf von Contains()
gegenüber anderen Objektmengen.
(rme [25])
URL dieses Artikels:
https://www.heise.de/-9649523
Links in diesem Artikel:
[1] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[2] https://github.com/dotnet/BenchmarkDotNet
[3] https://www.heise.de/blog/Neu-in-NET-8-0-1-Start-der-neuen-Blogserie-9574680.html
[4] https://www.heise.de/blog/Neu-in-NET-8-0-2-Neue-Anwendungsarten-9581213.html
[5] https://www.heise.de/blog/Neu-in-NET-8-0-3-Primaerkonstruktoren-in-C-12-0-9581346.html
[6] https://www.heise.de/blog/Neu-in-NET-8-0-4-Collection-Expressions-in-C-12-0-9581392.html
[7] https://www.heise.de/blog/Neu-in-NET-8-0-5-Typaliasse-in-C-12-0-9594693.html
[8] https://www.heise.de/blog/Neu-in-NET-8-0-6-ref-readonly-in-C-12-0-9602188.html
[9] https://www.heise.de/blog/Neu-in-NET-8-0-7-Optionale-Parameter-in-Lambda-Ausdruecken-in-C-12-0-9609780.html
[10] https://www.heise.de/blog/Neu-in-NET-8-0-8-Verbesserungen-fuer-nameof-in-C-12-0-9616685.html
[11] https://www.heise.de/blog/Neu-in-NET-8-0-9-Neue-und-erweiterte-Datenannotationen-9623061.html
[12] https://www.heise.de/blog/Neu-in-NET-8-0-10-Plattformneutrale-Abfrage-der-Privilegien-9630577.html
[13] https://www.heise.de/blog/Neu-in-NET-8-0-11-Neue-Zufallsfunktionen-9637003.html
[14] https://www.heise.de/blog/Neu-in-NET-8-0-12-Eingefrorene-Objektmengen-9643310.html
[15] https://www.heise.de/blog/Neu-in-NET-8-0-12-Leistung-von-FrozenSet-9649523.html
[16] https://www.heise.de/blog/Neu-in-NET-8-0-14-Neue-Waechtermethoden-fuer-Parameter-9656153.html
[17] https://www.heise.de/blog/Neu-in-NET-8-0-15-Geschluesselte-Dienste-bei-der-Dependency-Injection-9662004.html
[18] https://www.heise.de/blog/Neu-in-NET-8-0-16-Neue-Methoden-fuer-IP-Adressen-9670497.html
[19] https://www.heise.de/blog/Neu-in-NET-8-0-17-Zeitabstraktion-fuer-Tests-mit-Zeitangaben-9675891.html
[20] https://www.heise.de/blog/Neu-in-NET-8-0-18-Ein-Zeitraffer-mit-eigenem-FakeTimeProvider-9683197.html
[21] https://www.heise.de/blog/Neu-in-NET-8-0-19-Razor-HTML-Rendering-in-beliebigen-NET-Anwendungen-9691146.html
[22] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-NET-Basisklassen-9706875.html
[23] https://www.heise.de/blog/Neu-in-NET-8-0-20-Neue-Code-Analyzer-fuer-ASP-NET-Core-9710151.html
[24] https://www.heise.de/blog/Neu-in-NET-8-0-22-Neues-Steuerelement-OpenFolderDialog-fuer-WPF-9722901.html
[25] mailto:rme@ix.de
Copyright © 2024 Heise Medien