【问题标题】:Does Rust optimize passing temporary structures by value?Rust 是否优化了按值传递临时结构?
【发布时间】:2015-04-02 23:40:10
【问题描述】:

假设我在 Rust 中有一个结构向量。结构相当大。当我想插入一个新的时,我会这样写代码:

my_vec.push(MyStruct {field1: value1, field2: value2, ... });

推送定义是

fn push(&mut self, value: T)

表示值是按值传递的。我想知道 Rust 是先创建一个临时对象,然后再复制到 push 函数,还是优化代码以便不创建和复制临时对象?

【问题讨论】:

    标签: rust


    【解决方案1】:

    让我们看看。 This program:

    struct LotsOfBytes {
        bytes: [u8; 1024]
    }
    
    #[inline(never)]
    fn consume(mut lob: LotsOfBytes) {
    }
    
    fn main() {
        let lob = LotsOfBytes { bytes: [0; 1024] };
        consume(lob);
    }
    

    编译为以下 LLVM IR 代码:

    %LotsOfBytes = type { [1024 x i8] }
    
    ; Function Attrs: noinline nounwind uwtable
    define internal fastcc void @_ZN7consume20hf098deecafa4b74bkaaE(%LotsOfBytes* noalias nocapture dereferenceable(1024)) unnamed_addr #0 {
    entry-block:
      %1 = getelementptr inbounds %LotsOfBytes* %0, i64 0, i32 0, i64 0
      tail call void @llvm.lifetime.end(i64 1024, i8* %1)
      ret void
    }
    
    ; Function Attrs: nounwind uwtable
    define internal void @_ZN4main20hf3cbebd3154c5390qaaE() unnamed_addr #2 {
    entry-block:
      %lob = alloca %LotsOfBytes, align 8
      %lob1 = getelementptr inbounds %LotsOfBytes* %lob, i64 0, i32 0, i64 0
      %arg = alloca %LotsOfBytes, align 8
      %0 = getelementptr inbounds %LotsOfBytes* %lob, i64 0, i32 0, i64 0
      call void @llvm.lifetime.start(i64 1024, i8* %0)
      call void @llvm.memset.p0i8.i64(i8* %lob1, i8 0, i64 1024, i32 8, i1 false)
      %1 = getelementptr inbounds %LotsOfBytes* %arg, i64 0, i32 0, i64 0
      call void @llvm.lifetime.start(i64 1024, i8* %1)
      call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %0, i64 1024, i32 8, i1 false)
      call fastcc void @_ZN7consume20hf098deecafa4b74bkaaE(%LotsOfBytes* noalias nocapture dereferenceable(1024) %arg)
      call void @llvm.lifetime.end(i64 1024, i8* %1)
      call void @llvm.lifetime.end(i64 1024, i8* %0)
      ret void
    }
    

    这一行特别有趣:

    call fastcc void @_ZN7consume20hf098deecafa4b74bkaaE(%LotsOfBytes* noalias nocapture dereferenceable(1024) %arg)
    

    如果我理解正确,这意味着 consume 是用指向 LotsOfBytes 的指针调用的,所以是的,rustc 优化了按值传递大结构。

    【讨论】:

      猜你喜欢
      • 2022-06-25
      • 2012-03-04
      • 2012-01-17
      • 1970-01-01
      • 2017-11-11
      • 2015-03-12
      • 2023-02-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多