使用 .ET 8 中的 FrozenCollection
使用 .ET 8 中的 FrozenCollection
使用 .ET 8 中的 FrozenCollection
.ET 8 中引入了 FrozenCollection 使得只读 Collection 的操作性能更加好了,Stephen 在 .ET 8 的性能改进博客中也有提到,在只读的场景可以考虑使用 FrozenSet
/FrozenDictionary
来提升性能
FrozenSet
/FrozenDictionary
实现大致原理差不多,所以我们以 FrozenSet
来分析
很多人可能会问不是已经有了 ImmutableHashSet
/ImmutableDictionary
吗,为什么还要引入 FrozenSet
/FrozenDictinary
呢?我也有着同样的问题,其实仔细看 Stephen 的博客的话其实有解释的
The collecti in System.Collecti.Frozen are immutable, just as are those in System.Collecti.Immutable, but they’re optimized for a different scenario. Whereas the purpose of a type like ImmutableDictionary<TKey, TValue> is to enable efficient mutation (into a new instance), the purpose of FrozenDictionary<TKey, TValue> is to represent data that never changes, and thus it doesn’t expose any operati that suggest mutation, only operati for reading. Maybe you’re loading some configuration data into a dictionary once when your process starts (and then re-loading it only rarely when the configuration changes) and then querying that data over and over and over again. Maybe you’re creating a mapping from HTTP status codes to delegates representing how those status codes should be handled. Maybe you’re caching schema information about a set of dynamically-discovered types and then using the resulting parsed information every time you encounter those types later on. Whatever the scenario, you’re creating an immutable collection that you want to be optimized for reads, and you’re willing to spend some more cycles creating the collection (because you do it only once, or only once in a while) in order to make reads as fast as possible. That’s exactly what FrozenDictionary<TKey, TValue> and FrozenSetprovide.
System.Collecti.Frozen 中的集合是不可变的,就像 System.Collecti.Immutable 中的集合一样,但它们针对不同的场景进行了优化。ImmutableDictionary<TKey, TValue> 等类型的目的在于实现高效变异(进入新实例),而 FrozenDictionary<TKey, TValue> 的目的在于表示永不改变的数据,因此它不会公开任何暗示变异的操作,只公开读取操作。也许您在进程启动时将一些配置数据加载到字典中一次(然后仅在配置更改时偶尔重新加载它),然后一遍又一遍地查询该数据。也许您正在创建从 HTTP 状态代码到代表应如何处理这些状态代码的委托的映射。也许您正在缓存有关一组动态发现的类型的架构信息,然后在以后每次遇到这些类型时使用生成的解析信息。无论哪种情况,您都会创建一个不可变集合,并希望对其进行优化以进行读取,并且您愿意花费更多周期来创建该集合(因为您只执行一次或偶尔执行一次),以便尽可能快地进行读取。这正是 FrozenDictionary<TKey, TValue> 和 FrozenSet所提供的。
我们可以看下他们的实现代码
ImmutableHashSet
FrozenSet
可以看到 ImmutableHashSet
虽然是不可变的,在它的基础上 Add/Remove 会创建新的对象,这也造成的 ImmutableHashSet
的复杂,而我们去看 FrozenSet
可以看到它的 Add
/Remove
实现并没有实现,直接 throw 了 otSupportedException
我们来对 HashSet
/ImmutableHashSet
/FrozenSet
做一个查的基准测试,测试代码如下:
[MemoryDiagnoser]
[SimpleJob]
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory), CategoriesColumn] //
publicclassFrozenSetTest
{
private HashSet<string> _hashSet;
private ImmutableHashSet<string> _immutableHashSet;
private FrozenSet<string> _frozenSet;
[GlobalSetup]
public void Setup()
{
var array = Enumerable.Range(0, 10).Select(x => x.ToString()).ToArray();
_hashSet = array.ToHashSet();
_immutableHashSet = array.ToImmutableHashSet();
_frozenSet = array.ToFrozenSet();
}
[Benchmark(Baseline = true)]
[BenchmarkCategory("Contains")]
public bool FrozenSetContains()
{
return _frozenSet.Contains("6");
}
[Benchmark]
[BenchmarkCategory("Contains")]
public bool HashSetContains()
{
return _hashSet.Contains("6");
}
[Benchmark]
[BenchmarkCategory("Contains")]
public bool ImmutableHashSetContains()
{
return _immutableHashSet.Contains("6");
}
[Benchmark(Baseline = true)]
[BenchmarkCategory("otContains")]
public bool FrozenSetotContains()
{
return _frozenSet.Contains("-1");
}
[Benchmark]
[BenchmarkCategory("otContains")]
public bool HashSetotContains()
{
return _hashSet.Contains("-1");
}
[Benchmark]
[BenchmarkCategory("otContains")]
public bool ImmutableHashSetotContains()
{
return _immutableHashSet.Contains("-1");
}
}
这里的基准测试分成了两个 category,这里也分享下如何在一个 benchmark 类型中声明两组 benchmark
可以通过 BenchmarkCategory
来设置并指定 GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)
,这样在每个 category 下都可以有一个 Baseline
测试结果如下:
benchmark
从上述结果可以看得出来,Contains
/otContains
这两种均是 FrozenSet
的性能更加优秀,Dictionary 大家可以自己动动手尝试一下
除了前面说的 FrozenSet
没有 ImmutableHashSet
支持 Add
/Remove
之外,FrozenSet
/FrozenDictionary
也通过算法为只读做了更多的优化所以有更好的性能
所以在遇到只读 collection 判断的时候,可以使用 FrozenSet
代替 HashSet
/ImmutableHashSet
, 使用 FrozenDictionary
代替 Dictionary
/ImmutableDictionary
来改进性能
- .cs
- .Artifacts/results/PerformanceTest.CollectionTest.
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 6 条评论) |
本站网友 京海铭筑 | 27分钟前 发表 |
就像 System.Collecti.Immutable 中的集合一样 | |
本站网友 怎么去细纹 | 12分钟前 发表 |
也许您正在缓存有关一组动态发现的类型的架构信息 | |
本站网友 什么叫车震 | 19分钟前 发表 |
原始发表:2025-01-22 | |
本站网友 驻马店二手房 | 26分钟前 发表 |
原始发表:2025-01-22 | |
本站网友 络石藤 | 2分钟前 发表 |
ImmutableDictionary<TKey |