Rust 中的 Result<T, E> 怎么这么快?

问题描述 投票:0回答:1

如果您去年一直活跃在编程社区中,那么您肯定听到过对 Rust 执行速度和性能以及 Rust 中出色的

Result
类型的赞扬。

我可能应该提一下,我不是 Rust 开发人员。 尽管如此,或者甚至可能正因为如此,我想知道如果 Rust 使用这个 Result 类型,它怎么会如此高效,因为就我而言,这个类型被实现为所谓的

union
位于 C。它在联合中包含一个错误和一个返回值,其中在给定时间只有一个有效。该类型还包含一个标志,指示结果是否包含错误或值。

如果我计数正确,并且假设错误存储为指针或引用(例如,在 64 位系统上占用内存中的 8 个字节),则联合至少需要 8 个字节 + 标志需要一个字节,占用 9 个字节的内存。

现在有了填充,我假设在大多数系统上,这将被重新对齐以占用 12 个字节。 相比之下,返回 int(32) 仅分配 4 个字节。因此,使用 Result 分配的内存应该是使用 int 的三倍。

这不是极度浪费内存吗?我想象在循环中运行它,这会增加很多。

我不太明白为什么有人会声称 Rust 性能超强,而 Result 却占用了那么多内存?

我知道有一些优化技巧可以减少内存使用量,例如使用带有选项的 NotZeroInt 使编译器可以使用零作为标志,从而避免为标志提供额外的字节。但对于大多数类型来说这并不适用,不是吗?

如果有人有进一步的见解,我很想听听。 请注意,我不是 Rust 开发人员,出于好奇而提出这个问题,正如我在尝试移植此功能的库中观察到的那样,内存使用量急剧增加。

Rust 的

Result<T, E>
Option<T>
类型确实比某些移植库进行了更好的优化,但我无法想象这如何不会影响程序性能。

performance rust memory union memory-alignment
1个回答
0
投票

Rust 在如何分配枚举判别式方面比 C 的标记联合更加智能和优化,因为无法直接访问它们。此外,Rust 将泛型作为本机功能,这意味着 Result 布局是单独定义的,并针对所使用的 T 和 E 的每种组合进行了优化。

由于泛型,不需要使用引用,值直接包含在结果枚举的联合中。这意味着在大多数情况下,如果错误是错误代码,则最小错误 + 标志为 2 个字节。 (一个用于错误判别式,一个用于标志判别式)。

但是,您还需要能够返回一个值,并且该值是正常情况。该值通常有填充并且大于错误值。如果是这种情况,Rust 编译器能够对结果的鉴别器使用填充,从而产生一个与其最大值大小相同的标记枚举。这可以让您在内存使用方面有效地释放 Result 对象。

© www.soinside.com 2019 - 2024. All rights reserved.