提升Apache Arrow读写性能
我最后选了一个更保守的办法不改 Arrow .NET 的默认实现基于它已有的压缩扩展点单独做一个可选库。也就是这个dotnet add package ArrowNet.Compression.NativeCompressions项目地址https://github.com/InCerryGit/ArrowNet.Compression.NativeCompressions这个库不是 Apache Arrow 官方包而是一个可选的高性能压缩后端。它通过 Apache Arrow .NET 暴露出来的ICompressionCodecFactory扩展点把底层压缩实现换成了 Cysharp 的 NativeCompressions。NativeCompressions 仓库地址https://github.com/Cysharp/NativeCompressions性能对比#先直接看结果。Benchmark 环境BenchmarkDotNet 0.15.8Ubuntu 24.04.2 LTSIntel Core i7-14700K.NET SDK 10.0.107Runtime .NET 8.0.26测试的是 Arrow IPC 读写路径不是单纯的 codec micro benchmark。也就是说写入路径里包含 Arrow IPC writer 和MemoryStream.ToArray()的成本。测试命令dotnet run --project benchmarks/ArrowNet.Compression.NativeCompressions.Benchmarks/ArrowNet.Compression.NativeCompressions.Benchmarks.csproj -c Release -f net8.0 -- --filter *ArrowIpcCompressionBenchmarks*测试数据是 deterministic 的int stringArrow RecordBatch分别测试10w 行50w 行100w 行对比对象Apache.Arrow.Compression.CompressionCodecFactoryNativeCompressionsCodecFactory结果如下RowsPathCodecApache meanApache allocatedNative meanNative allocatedTime differenceAllocated difference100kWrite compressed IPC streamLZ4 frame3.229 ms6,105.70 KB2.716 ms5,291.66 KB15.9% faster13.3% less100kRead compressed IPC streamLZ4 frame0.764 ms3.79 KB0.431 ms3.07 KB43.5% faster19.0% less100kWrite compressed IPC streamZstd4.205 ms2,762.03 KB3.318 ms3,064.87 KB21.1% faster11.0% more100kRead compressed IPC streamZstd1.555 ms3.12 KB1.313 ms3.16 KB15.6% faster1.3% more500kWrite compressed IPC streamLZ4 frame15.844 ms28,698.06 KB14.929 ms26,426.71 KB5.8% faster7.9% less500kRead compressed IPC streamLZ4 frame4.039 ms4.10 KB2.235 ms3.42 KB44.7% faster16.6% less500kWrite compressed IPC streamZstd21.681 ms13,536.49 KB17.133 ms15,023.90 KB21.0% faster11.0% more500kRead compressed IPC streamZstd8.181 ms3.45 KB6.800 ms3.48 KB16.9% faster0.9% more1MWrite compressed IPC streamLZ4 frame36.852 ms57,450.92 KB32.276 ms52,845.62 KB12.4% faster8.0% less1MRead compressed IPC streamLZ4 frame8.619 ms4.11 KB4.761 ms3.22 KB44.8% faster21.7% less1MWrite compressed IPC streamZstd41.588 ms27,016.95 KB36.714 ms29,987.13 KB11.7% faster11.0% more1MRead compressed IPC streamZstd16.717 ms3.74 KB14.523 ms4.14 KB13.1% faster10.7% more可以看到最明显的是 LZ4 read 场景。在 10w、50w、100w 三组数据下NativeCompressions 后端快了大约 44%managed allocation 也更低。Zstd 这边也有时间收益不过内存分配上并不是所有场景都更好。尤其是 Zstd write速度更快但 managed allocation 会多一些。所以这个优化不能简单理解成“所有场景都更好”。更准确地说LZ4 read收益非常明显时间和 managed allocation 都更好LZ4 write时间更快allocation 更少Zstd read/write时间更快但 allocation 可能略高。性能优化不能只看一个指标。只看耗时容易忽略 allocation只看 allocation又可能错过真实吞吐收益。这里的 allocated 是 BenchmarkDotNetMemoryDiagnoser统计出来的 managed allocation per operation不是进程峰值内存也不是 native memory。关于 NativeCompressions#NativeCompressions 是 Cysharp 做的 native compression binding / high-level API。它支持LZ4ZstandardOpenZL对于 Arrow .NET 来说最相关的就是CompressionCodecType.Lz4FrameCompressionCodecType.Zstd正好对应 Arrow IPC 当前公开的两个压缩 codec。不过要注意NativeCompressions 当前仍然是 preview 状态。它的 README 里也明确写了 API 可能变化不建议直接无脑用于所有生产环境。在这个库里它只负责替换 Arrow IPC 的 LZ4/Zstd codec 实现。Arrow 的数据结构、IPC 格式、reader/writer API 还是 Apache Arrow .NET 的。Arrow .NET 是怎么接入压缩的#Apache Arrow .NET 这里设计得比较好它没有把压缩实现完全写死。它提供了一个扩展点ICompressionCodecFactory也就是说只要实现这个 factory就可以让 Arrow reader / writer 使用自己的 codec。使用方式大概是这样using Apache.Arrow.Ipc; using ArrowNet.Compression.NativeCompressions; var options new IpcOptions { CompressionCodecFactory new NativeCompressionsCodecFactory(), CompressionCodec CompressionCodecType.Lz4Frame };如果使用 Zstd把CompressionCodec改成CompressionCodecType.Zstd即可。所以这个库可以做得很小。不需要 fork Apache Arrow也不需要改 Arrow 的源码只需要实现它已经暴露出来的 codec factory 即可。NativeCompressionsCodecFactory 做了什么#核心入口就是NativeCompressionsCodecFactory它负责根据 Arrow 的CompressionCodecType创建对应 codec。目前只支持两个CompressionCodecType.Lz4Frame CompressionCodecType.Zstd不支持的 codec 会直接抛NotSupportedException。这样做有一个好处失败是显式的。压缩格式这种东西最怕静默 fallback。你以为用了某个高性能 backend实际却 fallback 到别的实现这种问题很难排查。所以这里宁可直接失败也不要偷偷降级。LZ4 和 Zstd 的实现思路#实现上分别有两个 internal codecNativeCompressionsLz4CompressionCodecNativeCompressionsZstdCompressionCodecLZ4 路径使用 NativeCompressions 的 LZ4 API。Zstd 路径使用 NativeCompressions 的 Zstandard API默认压缩级别是 3。更值得注意的是压缩路径没有使用 one-shotCompress(...)返回新byte[]的方式。一开始我也看过这个方向但这会引入额外的临时压缩数组。对于 Arrow IPC 写入来说本来就有 writer、buffer、stream、ToArray()等成本再多一个临时大数组会让 allocation 更难看。所以现在的实现使用了ArrayPoolbyte.Sharedspan-based output API最大压缩长度预估压缩完成后只写实际压缩长度这样做不是严格意义上的“零拷贝”但已经是比较接近当前接口约束下的 minimal-copy 路径。对于解压路径Arrow 会给出目标输出大小。codec 只需要把压缩 payload 解到 Arrow 期望的目标 buffer 里即可。这里还有一个细节Arrow IPC buffer 里可能存在 padding所以 decoder 不能简单假设输入长度就等于压缩帧的精确长度。实现需要遵守 Arrow 的 exact-output-size contract。Benchmark 是怎么设计的#Benchmark 不是只测 codec 本身而是测端到端 Arrow IPC 读写路径。主要有两个 benchmarkWriteCompressedIpcStream()

相关新闻

项目管理核心:比起完美规划,进度透明和风险前置更重要

项目管理核心:比起完美规划,进度透明和风险前置更重要

做项目久了,会发现一个很扎心的真相: 大多数团队根本不缺计划。 表格排得满满当当、任务拆分细致、人员分配到位,但最后依然延期、返工、节奏混乱。 问题到底出在哪? 答案从来不在「会不会规划」,而在「计划无法持续落…

2026/6/26 5:52:48阅读更多 →
GPT5.6下周登场价格战开启SK海力士招聘引行业巨震

GPT5.6下周登场价格战开启SK海力士招聘引行业巨震

听说没,OpenAI那个传说中的GPT-5.6系列,很可能下周就要露面了。这回一口气来三款:mini版、标准版,还有个Pro版。已经有Pro用户在网上晒图,说已经摸到GPT-5.6 Pro了,头一回用就感觉输出质量上了个大台阶。有…

2026/6/26 5:47:48阅读更多 →
实验室化学试剂购买平台有哪些

实验室化学试剂购买平台有哪些

购买实验室化学试剂,通常需要通过正规、资质齐全的第三方采购平台或品牌直营商城,以确保试剂纯度并符合国家对易制毒、易制爆等危险化学品的管控要求。目前主要有两类渠道:化学试剂品牌直营商城、综合性科研采购平台。1. 化学试剂品牌直营商城…

2026/6/26 5:47:48阅读更多 →
微服务启动的时候报Seate在Spring中自动装配失败

微服务启动的时候报Seate在Spring中自动装配失败

报错信息如下 org.springframework.beans.factory.BeanCreationException: Error creating bean with name globalTransactionScanner defined in class path resource [io/seata/spring/boot/autoconfigure/SeataAutoConfiguration.class]: Invocation of init method failed…

2026/6/26 7:17:54阅读更多 →
Microsoft Entra 外部 ID MFA 全栈实战:从租户配置到内外一体化防护

Microsoft Entra 外部 ID MFA 全栈实战:从租户配置到内外一体化防护

客户登录接口是网络攻击的核心目标,攻击者仅凭一套泄露或重复使用的密码,就足以攻破面向客户的应用系统。Microsoft Entra 外部 ID(原 Azure AD B2C)作为微软官方客户身份与访问管理(CIAM)平台,…

2026/6/26 7:17:54阅读更多 →
小白程序员必看:收藏!揭秘“循环工程师“如何驾驭AI,开启未来职场新篇章

小白程序员必看:收藏!揭秘“循环工程师“如何驾驭AI,开启未来职场新篇章

文章介绍了"循环工程师"这一新概念,它区别于传统程序员,是通过设计循环让AI自主完成设计、执行和修正工作。文章指出,未来职场将转向"判断"而非"执行",强调定义力、纠错力和连接力的重要性&#xf…

2026/6/26 7:17:54阅读更多 →
Buzz语音转录终极指南:如何用开源方案打造专业级本地音频处理平台

Buzz语音转录终极指南:如何用开源方案打造专业级本地音频处理平台

Buzz语音转录终极指南:如何用开源方案打造专业级本地音频处理平台 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz …

2026/6/26 7:17:54阅读更多 →
人工智能时代,SSD如何成为大模型训练与推理的“隐形引擎”?

人工智能时代,SSD如何成为大模型训练与推理的“隐形引擎”?

在AI大模型的训练和推理过程中,SSD(固态硬盘)扮演着远比多数人想象中更关键的角色。它不仅是海量训练数据的“粮仓”,更是GPU显存和系统内存的有力延伸,直接影响着模型加载速度、检查点保存效率和推理响应时间。随着模…

2026/6/26 7:17:54阅读更多 →
openYuanrong frontend:云原生函数网关的终极解决方案 [特殊字符]

openYuanrong frontend:云原生函数网关的终极解决方案 [特殊字符]

openYuanrong frontend:云原生函数网关的终极解决方案 🚀 【免费下载链接】yuanrong-frontend openYuanrong frontend:openYuanrong 网关,支持函数创建、调用等功能 项目地址: https://gitcode.com/openeuler/yuanrong-frontend…

2026/6/26 7:12:54阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/25 9:39:54阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/26 4:15:25阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/25 9:01:34阅读更多 →
HPE (慧与) 服务器专用 ESXi 9 全套官方定制资源详解 + 完整部署升级教程

HPE (慧与) 服务器专用 ESXi 9 全套官方定制资源详解 + 完整部署升级教程

一、前言:企业运维痛点与资源价值自博通收购 VMware 之后,原 VMware 公开免费下载渠道全面关闭,企业运维人员想要获取适配 HPE 慧与服务器的 ESXi 9 原厂镜像,必须注册博通账号、绑定有效授权才能下载,无授权账号无法获…

2026/6/26 0:02:15阅读更多 →
Kotlin的@JvmStatic与@JvmField:与Java互操作的注解

Kotlin的@JvmStatic与@JvmField:与Java互操作的注解

Kotlin作为一门现代编程语言,与Java的互操作性一直是其核心优势之一。为了让Kotlin代码能够无缝对接Java,Kotlin提供了多种注解来优化互操作体验,其中JvmStatic和JvmField是两个关键注解。它们分别用于解决静态成员和字段在Java中的访问问题&…

2026/6/26 0:02:15阅读更多 →
深入解析musl libc中的mmap实现源码

深入解析musl libc中的mmap实现源码

最近在阅读musl libc源码时,发现其mmap的实现非常精妙,特分享给大家。 一、代码整体结构 这段代码实现了__mmap函数,并通过weak_alias导出为mmap。这是典型的musl libc风格——提供弱符号以便用户可以重写。 weak_alias(__mmap, mmap); 二…

2026/6/26 0:02:15阅读更多 →