Hacker News 中文摘要

RSS订阅

Zig 的新异步 I/O -- Zig's New Async I/O

文章摘要

Zig语言在2026年路线图中引入了新的异步I/O接口,要求调用者提供Io接口的实现,类似于现有的Allocator。这一变化允许程序作者决定具体的I/O实现,并将其注入到依赖代码中,增强了灵活性和控制力。

文章总结

Zig 的新异步 I/O 设计

Zig Roadmap 2026 直播中,Andrew 宣布了 Zig 的一种新的 I/O 实现方式。本文将探讨这一新设计的目标,以及它如何与 Zig 中 async/await 的复兴相关。

新的 I/O 接口

Zig 最显著的变化是引入了一个新的接口 Io,负责所有 I/O 操作。与 Allocator 类似,Io 接口现在由调用者提供。这意味着程序的作者可以决定具体的 I/O 实现,并将其注入到依赖的代码中。

旧版 Zig 代码示例: ```zig const std = @import("std");

fn saveData(data: []const u8) !void { const file = try std.fs.cwd().createFile("save.txt", .{}); defer file.close();

try file.writeAll(data);

const out = std.io.getStdOut();
try out.writeAll("save complete");

} ```

新版 Zig 代码示例: ```zig const std = @import("std"); const Io = std.Io;

fn saveData(io: Io, data: []const u8) !void { const file = try Io.Dir.cwd().createFile(io, "save.txt", .{}); defer file.close(io);

try file.writeAll(io, data);

const out: Io.File = .stdout();
try out.writeAll(io, "save complete");

} ```

并发与并行

Io 接口还负责并发操作,尤其是在事件循环中。如果代码正确表达了操作的并发性Io 实现将有机会引入并行性

无并发示例: ```zig const std = @import("std"); const Io = std.Io;

fn saveData(io: Io, data: []const u8) !void { try saveFile(io, data, "saveA.txt"); try saveFile(io, data, "saveB.txt");

const out: Io.File = .stdout();
try out.writeAll(io, "save complete");

} ```

并发示例: ```zig const std = @import("std"); const Io = std.Io;

fn saveData(io: Io, data: []const u8) !void { var afuture = io.async(saveFile, .{io, data, "saveA.txt"}); var bfuture = io.async(saveFile, .{io, data, "saveB.txt"});

const aresult = afuture.await(io); const bresult = bfuture.await(io);

try aresult; try bresult;

const out: Io.File = .stdout(); try out.writeAll(io, "save complete"); } ```

取消支持

通过引入 Future.cancel(),Zig 实现了对取消操作的支持,而不会增加代码的复杂性。

取消支持示例: ```zig const std = @import("std"); const Io = std.Io;

fn saveData(io: Io, data: []const u8) !void { var afuture = io.async(saveFile, .{io, data, "saveA.txt"}); defer afuture.cancel(io) catch {};

var bfuture = io.async(saveFile, .{io, data, "saveB.txt"}); defer bfuture.cancel(io) catch {};

try afuture.await(io); try bfuture.await(io);

const out: Io.File = .stdout(); try out.writeAll(io, "save complete"); } ```

标准库的 I/O 实现

Zig 标准库将提供多种 Io 实现,包括阻塞 I/O、线程池、绿色线程和无栈协程。其中,绿色线程和无栈协程的实现依赖于 io_uring 和类似的系统 API。

设计目标

Zig 的新异步 I/O 设计旨在提高代码的可重用性和性能。通过将 async/await 与执行模型解耦,Zig 实现了“无函数染色”的目标,即代码可以在同步和异步模式下无缝运行。

语义化 I/O 操作

新的 Writer 接口引入了两个新原语:sendFiledrain,分别用于优化文件传输和向量化写入。

路线图

部分新功能将在 Zig 0.15.0 中引入,但大部分功能将在后续版本中发布,因为标准库的许多部分需要重写以适应这些新特性。

支持 Zig

如果你认为 Zig 是一个有前景的项目,请考虑通过 Every.orgGitHub Sponsors 支持我们。

常见问题

  • Zig 为什么关心异步?
    Zig 的目标是确保开发者能够充分利用非阻塞系统调用,以最大化 CPU 使用率。

  • 包作者是否必须使用异步?
    不是,普通的顺序代码仍然可以与用户选择的 I/O 策略兼容。

  • 是否可以插入任何执行模型?
    是的,除非代码中存在编程错误。

通过这一新的异步 I/O 设计,Zig 进一步巩固了其在并发编程领域的优势。

评论总结

  1. 正面评价

    • 评论1认为文章写得很好,特别对WebAssembly的潜在应用感到兴奋,提到WASI在用户空间的应用和自带IO的可能性。
      • 引用:"This is very well written, and very exciting! I especially love the implications for WebAssembly -- WASI in userspace? Bring your own IO? Why not both!"
    • 评论9虽然不喜欢io参数随处可见,但赞赏其允许多种实现(如基于线程、基于纤程等),并避免用户了解或关心具体实现,类似于Allocator接口。
      • 引用:"Although I'm not wild about the new io parameter popping up everywhere, I love the fact that it allows multiple implementations (thread based, fiber based, etc.) and avoids forcing the user to know and/or care about the implementation, much like the Allocator interface."
  2. 对函数着色问题的质疑

    • 评论2认为Zig并未真正解决函数着色问题,指出虽然不再有async/sync/red/blue函数,但仍有IO和非IO函数,且调用IO函数仍需提供IO参数。
      • 引用:"I disagree with this. Let's look at the 5 rules referenced in the famous 'What color is your function?' article referenced here."
    • 评论8也认为函数着色问题未被解决,指出Zig提供了多种实现选项,但真正的选择要么是阻塞IO,要么是使用纤程,要么是函数着色。
      • 引用:"It doesn't appear that the function colors problem has been defeated. Also, it appears to me that the Zig team decided to have every concurrency technique in the hope that it would appear innovative."
  3. 对纤程(green threads)的担忧

    • 评论4对Zig全面采用纤程表示遗憾,指出Rust在1.0之前就移除了Runtime trait,因为其性能不佳,担心Zig的性能可能只能与Go相当,而无法成为真正的性能竞争者。
      • 引用:"I'm generally a fan of Zig, but it's a little sad seeing them go all in on green threads (aka fibers, aka stackful coroutines)."
    • 评论8也提到Rust移除纤程的原因,并指出纤程在Go中有效是因为有垃圾回收器。
      • 引用:"Use green threads, which Rust removed [2] for good reasons [3]. It only works in Go because of the garbage collector."
  4. 对运行时多态性的质疑

    • 评论5认为像Zig这样的系统语言要求运行时多态性来处理标准IO操作似乎不妥,质疑为何在几乎所有实际情况下已知具体IO实现时还要强制增加运行时开销。
      • 引用:"Seeing a systems language like Zig require runtime polymorphism for something as common as standard IO operations seems off to me -- why force that runtime overhead on everyone when the concrete IO implementation could be known statically in almost all practical cases?"
  5. 对异步IO的正面评价

    • 评论7赞赏io.async表达异步性(操作可以无序发生但仍能正确执行)而不请求并发性,认为这分离了异步的含义与IO调用的作用。
      • 引用:"This is the key point for me. Regardless of whether you’re under an async event loop, you can specify that the order of your io calls does not imply sequencing. Brilliant. Separate what async means from what the io calls do."

总结:评论中对Zig的新特性有正面评价,特别是对WebAssembly的潜在应用和允许多种IO实现的灵活性表示赞赏。然而,对Zig是否真正解决了函数着色问题、全面采用纤程的性能影响以及运行时多态性的必要性提出了质疑。