开发日志

此页面包含 Zig 主分支最新变化的精选列表。

也可通过 RSS 源 获取。

本页面包含 2025 年的条目。其他年份可在开发日志存档页面中查看。

2025年6月30日

Zig 2026 年路线图

作者:Loris Cro

我们已安排于 7 月 2 日播放一集新的 Zig SHOWTIME,与 Andrew 讨论 Zig 2026 年的路线图。

更多信息请查看 https://zig.show/episodes/41/

2025 年 6 月 14 日

并行自托管代码生成

作者:Matthew Lugg

不到一周前,我们终于在 Linux 和 macOS 上默认开启了用于 Debug 构建的 x86_64 后端。今天,我们又对其进行了大幅性能改进:我们进一步并行化了编译器流水线!

这些改进不影响 LLVM 后端,因为它使用了更多共享状态;事实上,它仍然限于单个线程,而其他所有后端在此更改之前都能够使用两个线程。但对于自托管后端,机器代码生成本质上是一个独立任务,因此我们可以将其与其他所有任务并行运行,甚至可以同时运行多个代码生成任务。生成的机器代码最终会在链接器线程上全部拼接在一起。这意味着我们最终将有一个线程执行语义分析,任意数量的线程执行代码生成,以及一个线程执行链接。并行化此阶段特别有益,因为由于 x86_64 架构的各种扩展和指令,指令选择极其复杂。

这项工作最终促成了我和 Jacob 共同创建的拉取请求,该请求已于几天前合并。这项工作量不小,因为编译器流水线的许多内部细节需要重做,以完全将机器代码生成与链接器隔离。但最终为了性能提升,这一切都是值得的!使用自托管的 x86_64 后端,我们看到编译 Zig 项目的实际耗时有 5% 到 50% 的改进。例如,Andrew 报告说他能够在 10 秒或更短的时间内构建 Zig 编译器本身(不包括链接 LLVM,这会增加几秒钟时间)

Benchmark 1 (32 runs): [... long command to build compiler with old compiler ...]
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          13.8s  ± 71.4ms     13.7s … 13.8s           0 ( 0%)        0%
  peak_rss           1.08GB ± 18.3MB    1.06GB … 1.10GB          0 ( 0%)        0%
  cpu_cycles          109G  ± 71.2M      109G  …  109G           0 ( 0%)        0%
  instructions        240G  ± 48.3M      240G  …  240G           0 ( 0%)        0%
  cache_references   6.42G  ± 7.31M     6.41G  … 6.42G           0 ( 0%)        0%
  cache_misses        450M  ± 1.02M      449G  …  451G           0 ( 0%)        0%
  branch_misses       422M  ±  783K      421M  …  423M           0 ( 0%)        0%
Benchmark 2 (34 runs): [... long command to build compiler with new compiler ...]
  measurement          mean ± σ            min … max           outliers         delta
  wall_time         10.00s  ± 32.2ms     9.96s … 10.0s           0 ( 0%)        ⚡- 27.4% ±  0.9%
  peak_rss           1.35GB ± 18.6MB    1.34GB … 1.37GB          0 ( 0%)        💩+ 25.7% ±  3.9%
  cpu_cycles         95.1G  ±  371M     94.8G  … 95.5G           0 ( 0%)        ⚡- 12.8% ±  0.6%
  instructions        191G  ± 7.30M      191G  …  191G           0 ( 0%)        ⚡- 20.6% ±  0.0%
  cache_references   5.93G  ± 33.3M     5.90G  … 5.97G           0 ( 0%)        ⚡-  7.5% ±  0.9%
  cache_misses        417M  ± 4.55M      412M  …  421M           0 ( 0%)        ⚡-  7.2% ±  1.7%
  branch_misses       391M  ±  549K      391M  …  392M           0 ( 0%)        ⚡-  7.3% ±  0.4%

作为另一个数据点,我测得构建一个简单的“Hello World”所需时间缩短了 30%。

Benchmark 1 (15 runs): /home/mlugg/zig/old-master/build/stage3/bin/zig build-exe hello.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           355ms ± 4.04ms     349ms …  361ms          0 ( 0%)        0%
  peak_rss            138MB ±  359KB     138MB …  139MB          0 ( 0%)        0%
  cpu_cycles         1.61G  ± 16.4M     1.59G  … 1.65G           0 ( 0%)        0%
  instructions       3.20G  ± 57.8K     3.20G  … 3.20G           0 ( 0%)        0%
  cache_references    113M  ±  450K      112M  …  113M           0 ( 0%)        0%
  cache_misses       10.5M  ±  122K     10.4M  … 10.8M           0 ( 0%)        0%
  branch_misses      9.73M  ± 39.2K     9.67M  … 9.79M           0 ( 0%)        0%
Benchmark 2 (21 runs): /home/mlugg/zig/master/build/stage3/bin/zig build-exe hello.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           244ms ± 4.35ms     236ms …  257ms          1 ( 5%)        ⚡- 31.5% ±  0.8%
  peak_rss            148MB ±  909KB     146MB …  149MB          2 (10%)        💩+  7.3% ±  0.4%
  cpu_cycles         1.47G  ± 12.5M     1.45G  … 1.49G           0 ( 0%)        ⚡-  8.7% ±  0.6%
  instructions       2.50G  ±  169K     2.50G  … 2.50G           1 ( 5%)        ⚡- 22.1% ±  0.0%
  cache_references    106M  ±  855K      105M  …  108M           1 ( 5%)        ⚡-  5.6% ±  0.4%
  cache_misses       9.67M  ±  145K     9.35M  … 10.0M           2 (10%)        ⚡-  8.3% ±  0.9%
  branch_misses      9.23M  ± 78.5K     9.09M  … 9.39M           0 ( 0%)        ⚡-  5.1% ±  0.5%

顺便说一句,我真的很喜欢优秀的 std.Progress 输出,所以忍不住提一下我现在是多么享受 _观察_ 编译器,看着它所做的一切工作。

即使有了这些数字,我们在编译器性能方面仍有很大的提升空间。未来对我们的自托管链接器以及将函数发出到最终二进制文件中的代码进行改进,可以帮助加快链接速度,链接现在有时是编译速度的瓶颈(您可以在上面的 asciinema 中实际看到这个瓶颈)。我们还希望提高我们生成的机器代码质量,这不仅能让 Debug 二进制文件表现更好,而且(也许与直觉相反)应该会进一步加快链接速度。我们关注的其他性能工作包括减少编译器在编译结束时(其“刷新”阶段)所做的工作量,以消除另一大块开销,以及(在更遥远的未来)并行化语义分析。

也许最重要的是,增量编译——多年来一直是 Zig 项目的一项长期投入——在某些情况下已非常接近默认启用,这将允许小的更改在毫秒级内重建。顺便说一句,请记住,只要您能接受可能的编译器错误,就可以 _现在_ 就尝试增量编译并开始享受其好处!如果您想了解更多信息,请查看跟踪问题

闲聊就到这里——我希望大家和我们一样对这些改进感到兴奋。Zig 的编译速度达到了前所未有的最佳水平,希望这也是它未来最慢的速度了 ;)

2025 年 6 月 8 日

自托管 x86 后端现在成为调试模式的默认选项

作者:Andrew Kelley

现在,当您以 x86_64 为目标时,Zig 默认将使用自己的 x86 后端,而不是使用 LLVM 将位码文件降低为目标文件。

Windows 上的默认设置尚未更改,因为需要先完成更多 COFF 链接器工作。

x86 后端现在通过了 1987 个行为测试,而 LLVM 后端通过了 1980 个。实际上共有 2084 个行为测试,但其中额外的测试通常与 LLVM 自己的 x86 后端测试套件重复,因此我们只在使用自托管 x86 进行测试时运行这些测试。总之,我的意思是 Zig 的 x86 后端在实现 Zig 语言方面现在比其 LLVM 后端 _更健壮_。

为什么要与 LLVM 在代码生成方面竞争?有一些原因,但主要是因为我们可以在编译速度上大幅超越 LLVM。

Benchmark 1 (6 runs): zig build-exe hello.zig -fllvm
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           918ms ± 32.8ms     892ms …  984ms          0 ( 0%)        0%
  peak_rss            214MB ±  629KB     213MB …  215MB          0 ( 0%)        0%
  cpu_cycles         4.53G  ± 12.7M     4.52G  … 4.55G           0 ( 0%)        0%
  instructions       8.50G  ± 3.27M     8.50G  … 8.51G           0 ( 0%)        0%
  cache_references    356M  ± 1.52M      355M  …  359M           0 ( 0%)        0%
  cache_misses       75.6M  ±  290K     75.3M  … 76.1M           0 ( 0%)        0%
  branch_misses      42.5M  ± 49.2K     42.4M  … 42.5M           0 ( 0%)        0%
Benchmark 2 (19 runs): zig build-exe hello.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           275ms ± 4.94ms     268ms …  283ms          0 ( 0%)        ⚡- 70.1% ±  1.7%
  peak_rss            137MB ±  677KB     135MB …  138MB          0 ( 0%)        ⚡- 36.2% ±  0.3%
  cpu_cycles         1.57G  ± 9.60M     1.56G  … 1.59G           0 ( 0%)        ⚡- 65.2% ±  0.2%
  instructions       3.21G  ±  126K     3.21G  … 3.21G           1 ( 5%)        ⚡- 62.2% ±  0.0%
  cache_references    112M  ±  758K      110M  …  113M           0 ( 0%)        ⚡- 68.7% ±  0.3%
  cache_misses       10.5M  ±  102K     10.4M  … 10.8M           1 ( 5%)        ⚡- 86.1% ±  0.2%
  branch_misses      9.22M  ± 52.0K     9.14M  … 9.31M           0 ( 0%)        ⚡- 78.3% ±  0.1%

对于像 Zig 编译器本身这样的大型项目,编译时间从 75 秒缩短到了 20 秒。

我们 _才刚刚开始_。我们已经开始着手完全并行化代码生成的工作。我们距离使增量编译与此后端结合使用时变得稳定和健壮也只差一些链接器增强和错误修复。在提高生成的 x86 代码质量方面仍有许多唾手可得的改进。接下来我们还将关注 aarch64——这项工作预计将因我们新的 Legalize pass 而加速。

CI 已完成相应提交的构建,因此您可以从下载页面获取最新的 master 分支构建版本自行尝试。

最后,在此温馨提醒,Zig 软件基金会是一个 501(c)(3) 非营利组织,其发展资金来自像您一样慷慨的人们的捐赠。如果您喜欢我们所做的工作,请帮助我们保持财务可持续性

2025 年 6 月 6 日

Zig 构建系统入门视频

作者:Loris Cro

几天前我在 YouTube 上发布了一个新视频,向那些尚未完全理解 Zig 构建系统的人展示如何入门。

在视频中,我展示了如何创建一个暴露 Zig 模块的包,以及如何在另一个 Zig 项目中导入该模块。6 月之后,我将为该系列添加更多视频,以涵盖构建系统的更多内容。

视频在此:https://youtu.be/jy7w_7JZYyw

2025 年 5 月 20 日

FreeBSD 和 NetBSD 交叉编译支持

作者:Alex Rønne Petersen

拉取请求 #23835#23913 现已合并。这意味着,使用 zig cczig build,您现在可以从任何机器构建面向 FreeBSD 14.0.0+ 和 NetBSD 10.1+ 的二进制文件,就像长期以来您能够为 Linux、macOS 和 Windows 做的那样。

这建立在我们已经用于 glibc 并很快也将用于其他目标的策略之上。对于任何给定的 FreeBSD/NetBSD 版本,我们为每个受支持的目标构建 libc 和相关库,然后从生成的 ELF 文件中提取公共符号信息。接着,我们将所有这些信息组合成一个非常紧凑的 abilists 文件,随 Zig 一起分发。最后,当用户在交叉编译时要求链接 libc,我们会加载 abilists 文件并为每个组成 libc 的库(libc.solibm.so 等)构建一个存根库,确保它准确反映了 libc 为目标架构和操作系统版本提供的符号,并具有预期的 soname。这一切都与 llvm-ifs 工具的工作方式非常相似。

我们目前从最新的已知 FreeBSD/NetBSD 版本导入 crt0 代码,并手动应用任何必要的补丁,使其适用于我们支持交叉编译的任何操作系统版本。这是必要的,因为操作系统有时会更改 crt0 ABI。我们最终希望用 Zig 重新实现 crt0 代码

我们还在 Zig 编译器中附带 FreeBSD/NetBSD 系统和 libc 头文件。然而,与我们生成的存根库不同,我们总是从最新版本的操作系统导入头文件。这是因为为每个操作系统版本提供单独的头文件会非常低效,而且我们实际上没有时间在每次导入时审核头文件并为所有新声明添加适当的版本守卫。不过,好消息是,我们确实接受在必要时添加版本守卫的补丁;我们的导入 glibc 头文件中已经有了许多此类贡献。

请试用此功能并报告您发现的任何错误!

我们还希望添加对 OpenBSD libcDragonfly BSD libc 的支持,但由于这些 BSD 无法从 Linux 方便地进行交叉编译,我们需要这些系统的热心用户提供帮助。除此之外,我们还在研究对 SerenityOSAndroidFuchsia libc 的支持。

2025 年 4 月 9 日

网站已更新至 Zine 0.10.0

作者:Loris Cro

Zig 官方网站现在使用独立版 Zine 构建。大量代码已被重写,因此如果您在网站上发现回退问题,请提交问题。仅限回退问题,谢谢!

通常,Zine 的更新不值得作为开发日志的条目,但最近的这次更新非常重要,因为 Zine 从一个奇特的 Zig 构建脚本变成了一个独立的执行文件。如果您以前对 Zine 感兴趣但一直没时间尝试,那么这个里程碑是尝试一下的好时机。运行 zine init 即可获得一个开箱即用的示例网站,其中也包含了开发日志功能。

附言:我还在页面上的每个条目中添加了日期,这可是大家期待已久的功能 :^)

2025 年 3 月 3 日

发布标签状态更新

0.14.0 版本即将发布。我们还没有完成发布说明,今天就到此为止。

明天早上我将创建标签,启动 CI,然后在构建过程中完成发布说明。

我知道有很多东西遗憾地未能入选。让我们尝试将它们纳入 0.14.1 或 0.15.0 版本。同时,大量主要和次要的增强功能已经落地,并将在明天首次亮相。

2025 年 2 月 24 日

改进的 UBSan 错误消息

作者:David Rubin

最近,我一直在大量使用 C 语言互操作,而其中一个严重缺失的是来自 UBSan 的清晰错误消息。当使用 zig cc 编译 C 语言时,Zig 提供了更好的默认设置,包括隐式启用 -fsanitize=undefined。这对于捕获细微错误并使 C 语言工作更易于忍受非常有用。然而,由于缺乏 UBSan 运行时,以前所有未定义行为都是通过 trap 指令捕获的。

例如,考虑这个 C 语言示例程序

#include <stdio.h>

int foo(int x, int y) {
    return x + y;
}

int main() {
    int result = foo(0x7fffffff, 0x7fffffff);
    printf("%d\n", result);
}

以前使用 zig cc 运行此程序会产生一个无用的错误

$ zig run test.c -lc
fish: Job 1, 'zig run empty.c -lc' terminated by signal SIGILL (Illegal instruction)

信息量不大!要理解出了什么问题,您必须在调试器中运行可执行文件。即使那样,追溯根本原因也可能令人望而生畏。许多新手遇到这个 Illegal instruction 错误,却未意识到 UBSan 默认是启用的,从而导致困惑。这个问题非常常见,足以需要一个专门的 Wiki 页面

随着新的 UBSan 运行时合并,体验彻底改变了。现在,您不再会看到模糊的 SIGILL,而是得到一个更有用的错误消息

$ zig run test.c -lc
thread 208135 panic: signed integer overflow: 2147483647 + 2147483647 cannot be represented in type 'int'
/home/david/Code/zig/build/test.c:4:14: 0x1013e41 in foo (test.c)
    return x + y;
             ^
/home/david/Code/zig/build/test.c:8:18: 0x1013e63 in main (test.c)
    int result = foo(0x7fffffff, 0x7fffffff);
                 ^
../sysdeps/nptl/libc_start_call_main.h:58:16: 0x7fca4c42e1c9 in __libc_start_call_main (../sysdeps/x86/libc-start.c)
../csu/libc-start.c:360:3: 0x7fca4c42e28a in __libc_start_main_impl (../sysdeps/x86/libc-start.c)
???:?:?: 0x1013de4 in ??? (???)
???:?:?: 0x0 in ??? (???)
fish: Job 1, 'zig run test.c -lc' terminated by signal SIGABRT (Abort)

现在,我们不仅能看到 _出了什么问题_(有符号整数溢出),还能看到 _它发生在哪里_——这是以前缺失的两个关键信息。

剩余限制

虽然新的运行时极大地改进了调试,但 LLVM 的 UBSan 运行时提供的两个功能我们尚未支持

  1. 在 C++ 中,UBSan 可以检测对象的 vptr 何时指示错误的动态类型或其生命周期何时尚未开始。支持此功能将需要复制 Itanium C++ ABI,但其复杂性不值得。
  2. 目前,运行时不会显示 assume_aligned__nonnull 等属性的精确位置。这应该相对容易添加,欢迎贡献!

如果您在尝试 Zig 时曾因神秘的 SIGILL 错误而感到沮丧,那么这次更新应该会使未定义行为的调试变得容易得多!

2025 年 2 月 7 日

无 Libc 的 Zig 现在超越 Glibc Zig

作者:Andrew Kelley

好吧,我知道我本该专注于问题分类和合并本月即将发布的版本的 PR,但为自己辩解一下,我在拖延时总能做出一些最好的工作。

言归正传,本周我们遇到了 CI 故障,原因是 Zig 的调试分配器创建了过多的内存映射。这干扰了 Jacob 在 x86 后端上的工作,所以我花时间重做了调试分配器

由于这是消除对编译时已知页面大小依赖的机会,我的工作基于贡献者 archbirdplus 的补丁,该补丁旨在为 Zig 标准库添加运行时已知页面大小支持。随着这一更改的落地,这意味着 Zig 最终可以在 Asahi Linux 上运行了。我最初将页面大小设置为编译时已知是我的错误。对此深感抱歉!

除了在运行时检测页面大小之外,新实现不再将每个页面设置为 0xaa 字节然后再设置为 0x00 字节,不再在释放时进行搜索,也不再依赖 treap 数据结构。相反,分配元数据以内联方式存储在页面上,使用在编译时计算的预缓存查找表

/// This is executed only at compile-time to prepopulate a lookup table.
fn calculateSlotCount(size_class_index: usize) SlotIndex {
    const size_class = @as(usize, 1) << @as(Log2USize, @intCast(size_class_index));
    var lower: usize = 1 << minimum_slots_per_bucket_log2;
    var upper: usize = (page_size - bucketSize(lower)) / size_class;
    while (upper > lower) {
        const proposed: usize = lower + (upper - lower) / 2;
        if (proposed == lower) return lower;
        const slots_end = proposed * size_class;
        const header_begin = mem.alignForward(usize, slots_end, @alignOf(BucketHeader));
        const end = header_begin + bucketSize(proposed);
        if (end > page_size) {
            upper = proposed - 1;
        } else {
            lower = proposed;
        }
    }
    const slots_end = lower * size_class;
    const header_begin = mem.alignForward(usize, slots_end, @alignOf(BucketHeader));
    const end = header_begin + bucketSize(lower);
    assert(end <= page_size);
    return lower;
}

这非常棒,因为您可以调整一些全局常量,然后获得最佳的槽位大小。末尾的断言意味着如果约束条件无法满足,您将得到一个编译错误。同时在 C 语言领域,等效代码不得不诉诸于手工制作的查找表。只需看看 musl 中 malloc.c 的顶部

const uint16_t size_classes[] = {
	1, 2, 3, 4, 5, 6, 7, 8,
	9, 10, 12, 15,
	18, 20, 25, 31,
	36, 42, 50, 63,
	72, 84, 102, 127,
	146, 170, 204, 255,
	292, 340, 409, 511,
	584, 682, 818, 1023,
	1169, 1364, 1637, 2047,
	2340, 2730, 3276, 4095,
	4680, 5460, 6552, 8191,
};

尝试不同大小类别远没有那么方便。水很暖和,Rich,快来吧!😛

总之,重做这个分配器后,它不仅支持运行时已知页面大小,避免创建过多内存映射,而且性能也比以前显著提高。这些更改的推动测试案例是这个退化的 ast-check 任务,使用调试编译器。

Benchmark 1 (3 runs): master/bin/zig ast-check ../lib/compiler_rt/udivmodti4_test.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          22.8s  ±  184ms    22.6s  … 22.9s           0 ( 0%)        0%
  peak_rss           58.6MB ± 77.5KB    58.5MB … 58.6MB          0 ( 0%)        0%
  cpu_cycles         38.1G  ± 84.7M     38.0G  … 38.2G           0 ( 0%)        0%
  instructions       27.7G  ± 16.6K     27.7G  … 27.7G           0 ( 0%)        0%
  cache_references   1.08G  ± 4.40M     1.07G  … 1.08G           0 ( 0%)        0%
  cache_misses       7.54M  ± 1.39M     6.51M  … 9.12M           0 ( 0%)        0%
  branch_misses       165M  ±  454K      165M  …  166M           0 ( 0%)        0%
Benchmark 2 (3 runs): branch/bin/zig ast-check ../lib/compiler_rt/udivmodti4_test.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          20.5s  ± 95.8ms    20.4s  … 20.6s           0 ( 0%)        ⚡- 10.1% ±  1.5%
  peak_rss           54.9MB ±  303KB    54.6MB … 55.1MB          0 ( 0%)        ⚡-  6.2% ±  0.9%
  cpu_cycles         34.8G  ± 85.2M     34.7G  … 34.9G           0 ( 0%)        ⚡-  8.6% ±  0.5%
  instructions       25.2G  ± 2.21M     25.2G  … 25.2G           0 ( 0%)        ⚡-  8.8% ±  0.0%
  cache_references   1.02G  ±  195M      902M  … 1.24G           0 ( 0%)          -  5.8% ± 29.0%
  cache_misses       4.57M  ±  934K     3.93M  … 5.64M           0 ( 0%)        ⚡- 39.4% ± 35.6%
  branch_misses       142M  ±  183K      142M  …  142M           0 ( 0%)        ⚡- 14.1% ±  0.5%

然而,我并没有止步于此。尽管我还有发布任务要处理,但这让我 _迫不及待_ 地想开发一个快速分配器——一个专为在 ReleaseFast 模式下构建的多线程应用程序设计的分配器。

这是一个棘手的问题。一个快速分配器需要通过存储线程局部状态来避免竞争,然而,它不能直接得知线程何时退出,所以一个线程必须定期尝试回收另一个线程的资源。还有生产者-消费者模式——一个线程只分配,而另一个线程只释放。一个简单的实现永远不会回收这部分内存。

灵感来了,200 行代码之后,我就有了一个可用的实现……当然是在 Jacob 帮我找到了几个逻辑错误之后。

我创建了《卡门的内存去哪儿了?》,并用它来测试几个特定的使用模式。这里的想法是,随着时间的推移,收集一个健壮的测试套件,进行模糊测试、基准测试等,以便更容易地在 Zig 中尝试新的分配器想法。

在那些精心设计的测试中取得好成绩后,我转向了 Zig 编译器本身的实际用例。由于它可以构建为带 libc 或不带 libc 的版本,这是测试两者之间性能差异的好方法。

以下是上面提到的相同退化情况,但使用了编译器的发布版本——glibc zig 与无 libc zig 的对比

Benchmark 1 (32 runs): glibc/bin/zig ast-check ../lib/compiler_rt/udivmodti4_test.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           156ms ± 6.58ms     151ms …  173ms          4 (13%)        0%
  peak_rss           45.0MB ± 20.9KB    45.0MB … 45.1MB          1 ( 3%)        0%
  cpu_cycles          766M  ± 10.2M      754M  …  796M           0 ( 0%)        0%
  instructions       3.19G  ± 12.7      3.19G  … 3.19G           0 ( 0%)        0%
  cache_references   4.12M  ±  498K     3.88M  … 6.13M           3 ( 9%)        0%
  cache_misses        128K  ± 2.42K      125K  …  134K           0 ( 0%)        0%
  branch_misses      1.14M  ±  215K      925K  … 1.43M           0 ( 0%)        0%
Benchmark 2 (34 runs): SmpAllocator/bin/zig ast-check ../lib/compiler_rt/udivmodti4_test.zig
  measurement          mean ± σ            min … max           outliers         delta
  wall_time           149ms ± 1.87ms     146ms …  156ms          1 ( 3%)        ⚡-  4.9% ±  1.5%
  peak_rss           39.6MB ±  141KB    38.8MB … 39.6MB          2 ( 6%)        ⚡- 12.1% ±  0.1%
  cpu_cycles          750M  ± 3.77M      744M  …  756M           0 ( 0%)        ⚡-  2.1% ±  0.5%
  instructions       3.05G  ± 11.5      3.05G  … 3.05G           0 ( 0%)        ⚡-  4.5% ±  0.0%
  cache_references   2.94M  ± 99.2K     2.88M  … 3.36M           4 (12%)        ⚡- 28.7% ±  4.2%
  cache_misses       48.2K  ± 1.07K     45.6K  … 52.1K           2 ( 6%)        ⚡- 62.4% ±  0.7%
  branch_misses       890K  ± 28.8K      862K  … 1.02M           2 ( 6%)        ⚡- 21.8% ±  6.5%

超越 glibc!

最后是编译器自行构建的性能表现

Benchmark 1 (3 runs): glibc/bin/zig build -Dno-lib -p trash
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          12.2s  ± 99.4ms    12.1s  … 12.3s           0 ( 0%)        0%
  peak_rss            975MB ± 21.7MB     951MB …  993MB          0 ( 0%)        0%
  cpu_cycles         88.7G  ± 68.3M     88.7G  … 88.8G           0 ( 0%)        0%
  instructions        188G  ± 1.40M      188G  …  188G           0 ( 0%)        0%
  cache_references   5.88G  ± 33.2M     5.84G  … 5.90G           0 ( 0%)        0%
  cache_misses        383M  ± 2.26M      381M  …  385M           0 ( 0%)        0%
  branch_misses       368M  ± 1.77M      366M  …  369M           0 ( 0%)        0%
Benchmark 2 (3 runs): SmpAllocator/fast/bin/zig build -Dno-lib -p trash
  measurement          mean ± σ            min … max           outliers         delta
  wall_time          12.2s  ± 49.0ms    12.2s  … 12.3s           0 ( 0%)          +  0.0% ±  1.5%
  peak_rss            953MB ± 3.47MB     950MB …  957MB          0 ( 0%)          -  2.2% ±  3.6%
  cpu_cycles         88.4G  ±  165M     88.2G  … 88.6G           0 ( 0%)          -  0.4% ±  0.3%
  instructions        181G  ± 6.31M      181G  …  181G           0 ( 0%)        ⚡-  3.9% ±  0.0%
  cache_references   5.48G  ± 17.5M     5.46G  … 5.50G           0 ( 0%)        ⚡-  6.9% ±  1.0%
  cache_misses        386M  ± 1.85M      384M  …  388M           0 ( 0%)          +  0.6% ±  1.2%
  branch_misses       377M  ±  899K      377M  …  378M           0 ( 0%)        💩+  2.6% ±  0.9%

我感觉这是 Zig 项目发展轨迹中的一个关键时刻。这最后一块拼图标志着该语言和标准库在使用上已变得比 C 和 libc _更好_。

当其他语言基于 libc 构建时,Zig 却征服了它!

2025 年 1 月 24 日

适用于 Zig 的 LLDB 分支

作者:Alex Rønne Petersen

Jacob (@jacobly0) 一直在努力的一项主要工作是为 Zig 提供良好的调试支持。这包括一个为 Zig 语言增强的 LLDB 分支,主要用于 Zig 的自托管后端。随着自托管 x86_64 后端在即将发布的 0.14.0 版本中变得更加可用,我决定撰写一个维基页面,提供构建和使用该分支的说明。

如果您已经在工作流程中试用 Zig 的自托管后端,请尝试使用 LLDB 分支,看看它如何满足您的需求。