QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

高性能的.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:122364
用户头像

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

关注

评论

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

Matlab实现PCA算法

Shine

三周年连更

eBPF的发展演进---从石器时代到成为神(五)

统信软件

操作系统 Linux Kenel

2023年免费的堡垒机就用行云管家!安全感满满!

行云管家

网络安全 等保 小微企业

干货好文 | 两地三中心到异地双活演变及关键技术探讨

沃趣科技

MySQL 数据库 opengauss

浅谈复杂业务系统的架构设计 | 京东云技术团队

京东科技开发者

架构 DDD 架构设计 企业号 4 月 PK 榜 复杂系统

软件测试/测试开发丨利用ChatGPT自动生成测试用例思维导图

测试人

软件测试 自动化测试 测试开发 测试用例 ChatGPT

GitHub经典教材!阿里P8的这份SpringBoot精髓到底厉害在哪里?

做梦都在改BUG

Java spring 微服务 Spring Boot 框架

节前超级干货福利放送!这可能是最实用的 Conan 管理依赖贴

Zilliz

非结构化数据 Milvus Zilliz 向量数据库 依赖管理

springboot升级过程中踩坑定位分析记录 | 京东云技术团队

京东科技开发者

spring Spring Boot release 企业号 4 月 PK 榜

深度学习模型可视化-keras版

AIWeker

Python 深度学习 可视化 keras 三周年连更

ShareSDK 新浪微博平台注册指南

MobTech袤博科技

如何优雅的使用策略模式

做梦都在改BUG

一文理清 TiDB 与 MySQL 中的常用字符集及排序规则

TiDB 社区干货传送门

新版本/特性解读 6.x 实践

BSN-DDC基础网络详解(十):官方DDC应用SDK

BSN研习社

任务编排:CompletableFuture从入门到精通

做梦都在改BUG

Java CompletableFuture

长春市做等保评测的公司有几家?名单有哪些?

行云管家

等保 等保测评 长春

新浪张俊林:大语言模型的涌现能力——现象与解释

NLP资深玩家

5月7日【飞天Club × 云原生技术实践营—飞天免费计划实践专场】开启报名

阿里巴巴云原生

阿里云 云原生 飞天Club

软件测试/测试开发丨面试题之软素质与反问面试官篇(附答案)

测试人

软件测试 自动化测试 测试开发 测试用例 ChatGPT

TiDB x Flink 数据集成实践

TiDB 社区干货传送门

TiDB x Flink x Iceberg 实时 ODS 实践

TiDB 社区干货传送门

TiSpark v3.0.3 & v3.1.3 发布

TiDB 社区干货传送门

新版本/特性解读

政务智能办体验升级、乳腺癌创新药加速研发,飞桨和文心大模型驱动应用智能涌现

飞桨PaddlePaddle

百度飞桨

中移链控制台对接4A平台功能验证介绍

BSN研习社

全球首个开发者村启动开村,产业聚力松山湖,共创大湾区创新高地

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 4 月 PK 榜

你不想成长,生活总会逼着你成长,阿里P8架构师分享十年学习生涯

程序知音

Java redis spring java架构 后端技术

从不均匀性角度浅析AB实验 | 京东云技术团队

京东科技开发者

A/B 测试 AB实验 企业号 4 月 PK 榜 不均匀 实验准确度

GitHub下载已过百万!阿里这份Java虚拟机源码剖析手册真的绝了

做梦都在改BUG

Java JVM 虚拟机

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