AICon 上海站|日程100%上线,解锁Al未来! 了解详情
写点什么

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

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

关注

评论

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

全民经纪人平台

深圳亥时科技

Late Chunking×Milvus:如何提高RAG准确率

Zilliz

Milvus LLM rag 大模型幻觉 late chunking

GreptimeDB vs. ClickHouse vs. ElasticSearch 日志引擎性能对比报告

Greptime 格睿科技

数据库 Elastic Search Click house 性能报告

计算不停歇,百度沧海数据湖存储加速方案 2.0 设计和实践

百度Geek说

人工智能 数据库 百度 数据湖

语忆科技携手火山引擎数据飞轮 探索智能客服场景新可能

字节跳动数据平台

大数据 数仓 数智化转型 数据飞轮

一文说清什么是数据要素

郑州埃文科技

数据要素

第二届全国高校软件测试开发教育峰会在韩山师范学院隆重举办!

测吧(北京)科技有限公司

测试

经济下行,当下企业如何破局?

禅道项目管理

需求管理 IPD 市场分析 IPD落地 IPD培训

数字身份发展趋势前瞻:身份韧性与安全

芯盾时代

身份安全 iam 统一身份管理平台

细谈 Linux 中的多路复用epoll

威哥爱编程

Linux epoll Java.

【堡垒机小知识】堡垒机用户认证是什么意思?一般有哪些方式?

行云管家

网络安全 堡垒机

深度解析1688阿里巴巴平台商品详情API接口

代码忍者

API 接口 pinduoduo API

如何利用模版进行设置仿真默认参数z

思茂信息

教程 模板 cst

【征程 6 工具链性能分析与优化-1】编译器预估 perf 解读与性能分析

地平线开发者

服装品牌必备:智能商品管理系统,打造高效运营新引擎!

第七在线

常规LED广告显示屏运营成本怎么估算

Dylan

广告 运营 LED display LED显示屏 全彩LED显示屏

DolphinScheduler集成Arthas实现接口调用监控,提升调度任务可靠性

白鲸开源

工作流调度 Apache DolphinScheduler #开源

基于图遍历的Flink任务画布模式下零代码开发实现方案

京东科技开发者

【征程 6 工具链性能分析与优化-2】模型性能优化建议

地平线开发者

自动驾驶; #算法

开源自托管数据管理工具全面指南

NocoBase

开源 数据管理 数据转换 自托管

艾卡货车救援系统(源码+文档+部署+讲解)

深圳亥时科技

指标+AI+BI:构建数据分析新范式

袋鼠云数栈

Kubernetes时代的APM部署革新:基于Webhook的Agent动态注入

云智慧AIOps社区

APM 应用监控

HyperWorks作业递交面板设置

智造软件

CAE Hypermesh hyperworks

Avalonia开源控件库强力推荐-Semi.Avalonia

沙漠尽头的狼

AI工具百宝箱|一键解锁o1/ChatGPT/Gemini/Claude等应用的网站,等你来体验!

可信AI进展

泄漏检测与修复综合管理系统(源码+文档+部署+讲解)

深圳亥时科技

如何配置 GreptimeDB 作为 Prometheus 的长期存储

Greptime 格睿科技

存储 时序数据库 Promethues

一起单测引起的项目加载失败惨案

京东科技开发者

非凸科技助力第49届ICPC亚洲区域赛(成都)成功举办

非凸科技

ICPC

2025郑州等保测评机构名称看这里!

行云管家

等保 等级保护 郑州

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