Performance 重复(x)。采取(n)执行吗?
我正在寻找一种有效的方法来编写以下函数,如中所述: Rust是否为泛型结构类型的实例生成具体类型?是重复('.')的结果。take(n)(结构Performance 重复(x)。采取(n)执行吗?,performance,rust,Performance,Rust,我正在寻找一种有效的方法来编写以下函数,如中所述: Rust是否为泛型结构类型的实例生成具体类型?是重复('.')的结果。take(n)(结构take)等效于 struct Take_Repeat_char { element: char, n: usize } 方法实现是否内联?是否有一个版本的Take::next()内联了Repeat::next() 什么是我自己检查这个的好方法?检查LLVM IR?是的,这是生锈的™ 足够地是的,如果您使用优化编译(例如,cargo bu
take
)等效于
struct Take_Repeat_char {
element: char,
n: usize
}
方法实现是否内联?是否有一个版本的Take::next()
内联了Repeat::next()
什么是我自己检查这个的好方法?检查LLVM IR?是的,这是生锈的™ 足够地是的,如果您使用优化编译(例如,
cargo build--release
),LLVM将嵌入整个过程。检查过孔并查看生成的部件。有关守则是:
movb $46, (%rax)
movb $46, 1(%rax)
movb $46, 2(%rax)
movb $46, 3(%rax)
movb $46, 4(%rax)
五个点。我相信将前四个点合并成一个点可能会更快
movd $x2e2e2e2e, (%rax)
指导,但我认为这不会有多大区别。编辑:实际上取决于内存对齐方式,它可能快一些,也可能慢一些:如果对齐了%rax
,它可能会快一些(取决于缓存、预取等复杂的事情),否则它可能会慢一些(因为可能存在陷阱)
Rust是否为泛型结构类型的实例生成具体类型
是的,这叫做单晶化
方法实现是内联的吗
像许多语言一样,这是一个坚实的“也许”。有两种方法可以控制内部和内部的内联,但通常由编译器来做正确的事情。如上所述,如果一个函数使用泛型类型,它将自动用于单组化,这意味着内联它所需的信息可以在编译的板条箱中获得
什么是我自己检查这个的好方法
许多人将使用来查看LLVM IR或程序集。当然,您可以使用rustc--emit[asm | llvm ir]
在本地查看它。在执行此操作时,我将感兴趣的代码放在一个永远不会内联的函数中。这使得在assembly/IR输出中更容易找到:
#[inline(never)]
fn dots(n: usize) -> String {
std::iter::repeat('.').take(n).collect()
}
正如前面所指出的,rustc和LLVM已经看穿了您的整个实现,并完全展开了它。不过,实现会根据需要的字符数进行更改
要知道它是否快,唯一的方法是分析它的轮廓。引用llogiq:
我相信将前四个点合并成一个movd
我主张在现实世界中测试任何这样的代码。程序集非常重要,尤其是x64/x86_64变体。指令可能有奇怪的管道要求,或者可能导致CPU的其他部分不可用
简介,简介,简介^_^ 这不是真正的表演,有点糟糕
const CAP: usize = 64 * 1024;
#[bench]
fn fill_string_repeat(b: &mut Bencher) {
b.iter(|| {
repeat('.').take(CAP).collect::<String>()
});
b.bytes = CAP as u64;
}
#[bench]
fn fill_string_vec(b: &mut Bencher) {
b.iter(|| {
String::from_utf8(vec![b'.'; CAP])
});
b.bytes = CAP as u64;
}
vec代码>解决方案要好得多,这包括占主导地位的UTF-8检查开销,使用String::from\u utf8\u unchecked
并获得:
test fill_string_vec_unchecked ... bench: 29,354 ns/iter (+/- 503) = 2232 MB/s
(这里基本上只保留了memset。)我不得不使用-1,因为它的性能不够。我们不能简单地重复“iterator inline great”(他们确实这么做)这句话来激发像“它优化到了好代码”这样的结论,这是不正确的。改进了BufWriter
construction:@bluss:fair够了——请注意,我并没有说这在所有情况下都有效,只是针对给定的特定示例。真的。内联的点(5)
看起来不错,你举了一个很好的例子,我用另一个不太好的例子回答。我认为重要的一点是,repeat().take()
并不总是产生最好的代码。我们可以说“足够好的编译器”还没有出现。内置于发布模式?
test fill_string_repeat ... bench: 240,467 ns/iter (+/- 719) = 272 MB/s
test fill_string_vec ... bench: 106,885 ns/iter (+/- 224) = 613 MB/s
test fill_string_vec_unchecked ... bench: 29,354 ns/iter (+/- 503) = 2232 MB/s