【QCon】精华内容上线92%,全面覆盖“人工智能+”的典型案例!>>> 了解详情
写点什么

高性能的.NET 不可变数组

  • 2013-07-05
  • 本文字数:1401 字

    阅读完需:约 5 分钟

最新发布的.NET不可变集合中包含了 ImmutableArray,一种在只读、索引化的场景中比 ImmutableList更快速的选择。ImmutableList在设计时选择了一种平衡的方案。由于其复杂的内部结构,添加新项只能是 O(log n) 的操作。同样,通过索引读取某项也要耗费 O(log n) 的时间。

ImmutableArray则没有这么复杂。它只是一个包装了数组的结构。用 ildasm 可以看到,它不包含任何其他字段。这意味着从不可变数组中读取只需要 O(1) 的时间。相反,向不可变数组添加一项则需要对实际数组进行完全拷贝,为 O(n) 操作。

Immo Landwerth 提出了以下建议:

使用不可变数组的理由:

  • 极少更新数据,并且元素数量很小(小于 16)
  • 对迭代数据的性能要求很高
  • 有很多不可变集合的实例,并且无法负担将它们全放在树中的开销。

仍然使用不可变列表的理由:

  • 更新数据比较常见,或者元素数量预计不会太小
  • 对更新集合的性能要求比迭代要高

作为一个值类型,ImmutableArray在创建时不需要显式初始化。此时,结构将检测到内部空指针,其行为就像是长度为 0 的数组。

重大改变

不可变集合正处于开发过程中,重大变更时有发生。这一次,我们看到 Create(IEnumerable items) 函数更名为“From”。

Immo 写到,

我们发现接受 IEnumerable参数的重载可能会产生意想不到的结果。你可能认为要通过其他集合创建集合可以使用接受 IEnumerable参数的重载:

但你最终创建的是 ImmutableList<List> 而不是 Immutable,这是因为在进行重载决策时,参数重载的优先级要高于从 List到 IEnumerable的隐式转换。

因此我们决定将所有操作 IEnumerable的工厂方法改名为 From,以消除这种歧义。

最初的 IImmutableList包含一个 ValueComparer 属性,并匹配 WithComparer 方法。为了让 ImmutableArray保持为一个简单的包装器,就有必要在 IImmutableList接口中移除它们。

扩展方法 GetValueOrDefault 曾经接受一个 IDictionary<TKey, TValue> 或 IReadOnlyDictionary<TKey, TValue>。如果实际的类同时实现了这两个接口就会引起编译器错误,因此用只接受 IImmutableDictaionary<TKey, TValue> 的版本进行了替换。

其他改变

IImmutableSet新增了 TryGetValue 方法。如果使用了比较器如 StringComparer.OrdinalIgnoreCase,并且想得到集中的实际值而不仅仅是判断是否存在等价的元素时,就需要使用该方法了。

不可变集合仍然是预览版,并且不允许在生产中使用。它们目前可用于.NET 4.5、Windows Store、Windows Phone 8 和 Portable Class Library。

数组的性能

Jon Skeet 最近测试了数组的性能并发现了一些有趣的结果。用包装器包装数组竟然可以使它们能够更快地写入。对一个包含 100 项的数组进行 1 亿次写入,字符串数组用了 40.865 秒,而包装的字符数组只用了 29.338 秒。读取速度两者差不多,字符数组用了 12 秒,包装的数组用了 11.843 秒。

其原因要追溯到 Java 了。Java 的数组是协变的,也就是说可以将一个 String[] 传递给任何期望 Object[] 的参数或变量。.NET 的运行时 CLR 要设计为支持 Java,所以也支持协变数组。因此在每次写入数组时 CLR 都需要执行一次类型检查。

Jon Skeet 的数组包装器与我们上面提到的 ImmutableArray 中使用的并不相同。它在内部对数组中的每一项使用了基于结构的包装器。由于它只是一个包含了指针的结构,因此并不比数组中存储的普通引用耗费更多的空间。但其设计可以使 CLR 的 JIT 编译器忽略类型检查。

查看英文原文 High Performance Immutable Arrays in .NET

2013-07-05 06:122033
用户头像

发布了 59 篇内容, 共 22.4 次阅读, 收获喜欢 3 次。

关注

评论

发布
暂无评论
发现更多内容

【网络安全篇】php伪协议-漏洞及其原理

贤鱼很忙

php 网络安全 Web 10月月更

【网络安全】如何在Apache 安装开源 WAF

网络安全学海

黑客 网络安全 信息安全 渗透测试

2022-10-11:一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b。 给你一组整数区间intervals,请找到一个最小的集合 S, 使得

福大大架构师每日一题

算法 rust 福大大

【Java深入学习】Park&Unpark的深入学习讲解

Geek_65222d

10月月更

sql注入--通过修改数据完成注入--一文详细讲解

贤鱼很忙

Web SQL注入 10月月更

数据中台4点核心建设内容

阿泽🧸

数据中台 10月月更

Docker下Nacos配置应用开发

程序员欣宸

nacos spring-cloud 10月月更

这是两个Gopher面试必知必会的知识点,你搞懂了吗?

王中阳Go

Go golang 面试题 channel 10月月更

啃论文俱乐部——移植speexdsp到OpenHarmony标准系统②

离北况归

OpenHarmony

Java文档注释 Intellij IDEA Generate JavaDoc

Yeats_Liao

后端 doc Java core 10月月更

Flash软件应用项目(一)

张立梵

设计师 Flash 10月月更

Redis 的快速介绍及其基本数据类型和操作

宇宙之一粟

redis 10月月更

Go容易搞错的知识点汇总

王中阳Go

Go 面试题 #go 10月月更 go面试题

【答读者问】把Go基础学完后,是学web方向还是区块链方向?

王中阳Go

php Go 区块链 职业规划 10月月更

使用 Scrapy 框架来爬取数据

攻城狮Wayne

spider scrapy框架 10月月更

Vue组件入门(二)props和emit

Augus

Vue3 10月月更

爬虫实例——爬取豆瓣网 top250 电影的信息

攻城狮Wayne

Python爬虫 10月月更 爬虫案例

前端工程师面试题自检篇(一)

loveX001

JavaScript

大数据ELK(二十二):采集Apache Web服务器日志

Lansonli

ELK 10月月更

啃论文俱乐部——移植speexdsp到OpenHarmony标准系统①

离北况归

OpenHarmony

云服务架构设计基础模式

穿过生命散发芬芳

10月月更 云服务架构

基础算法:二分查找 搜索插入位置

攻城狮Wayne

Python 二分查找 10月月更

cstdio的源码学习分析09-改变文件流文件流buffer函数setvbuf

桑榆

源码刨析 10月月更 C++

Web3雇佣兵的现状,Zebec根本上提高用户黏性

股市老人

Web3雇佣兵的现状,Zebec根本上提高用户黏性

EOSdreamer111

前端工程师面试题自检篇(二)

loveX001

JavaScript

sql注入--handler语句--一文详细解说其原理和方法

贤鱼很忙

Web SQL注入 10月月更

《数字经济全景白皮书》中国银行业场景金融生态建设分析2022 发布

易观分析

金融 客户 场景生态建设

网络异常之后为什么MOA地址列表错乱了?

BUG侦探

TCP Jedis 乱序

Spring之IOC自动装配

楠羽

笔记 SP【ring 10月月更

Web3雇佣兵的现状,Zebec根本上提高用户黏性

鳄鱼视界

高性能的.NET不可变数组_.NET_Jonathan Allen_InfoQ精选文章