.NET 7中两种List<(Guid, int)>元素Item2递增方式孰更高效?
.NET 7中List<(Guid, int)>元素Item2递增的两种实现性能对比
我有一个List<(Guid, int)>类型的值元组列表,需要递增指定索引位置元素的Item2字段,目前存在两种实现方案:
- 方案1:先获取指定索引处的元组副本,递增副本的
Item2字段,再将副本替换回原列表的对应位置 - 方案2:使用.NET 5引入的
CollectionsMarshal.AsSpanAPI,获取列表底层数组的Span<(Guid, int)>视图,原地更新目标元素的Item2字段
对应的实现代码如下:
static void Increment1(List<(Guid, int)> list, int index) { (Guid, int) copy = list[index]; copy.Item2++; list[index] = copy; } static void Increment2(List<(Guid, int)> list, int index) { Span<(Guid, int)> span = CollectionsMarshal.AsSpan(list); span[index].Item2++; }
性能对比结论
在.NET 7平台上,方案2的性能明显更优。
原因分析
- 方案1存在两次完整的元组拷贝操作:读取列表元素时会拷贝整个20字节的元组(16字节Guid + 4字节int),修改后写回列表时又会再拷贝一次,额外的内存拷贝会带来CPU和内存开销。
- 方案2通过
CollectionsMarshal.AsSpan直接访问列表的底层数组,操作Span元素时是原地修改Item2字段,不需要拷贝整个元组,仅需对目标字段执行递增操作,内存和CPU开销都远低于方案1。同时.NET 7的JIT编译器对Span操作有针对性优化,进一步降低了抽象开销,让原地修改的逻辑效率最大化。
内容的提问来源于stack exchange,提问作者Theodor Zoulias
相关产品推荐
相关产品推荐

