2015-07-07 19 views
7

Tôi có quyền giả định rằng điều duy nhất "chậm lại" Rc s là nó có kiểm tra xem có nên xử lý lại đối tượng khi nó rơi xuống không? Bên cạnh đó, "số tiền" là phí tổn của cuộc hội thảo là Rc, tức là tôi có nên lo lắng về điều đó không?
Hai chức năng này có gần như bằng nhau không? Hay có sự khác biệt đáng chú ý về tốc độ?Tôi có phải lo ngại về chi phí của `Rc` không?

fn test_with_box() { 
    let b = Box::new(1.0); 
    let x = b * 2; 
} 

fn test_with_rc() { 
    let rc = Rc::new(1.0); 
    let x = rc * 2; 
} 

Kể từ khi đối tượng được tham chiếu trong test_with_rc() luôn chỉ có một tài liệu tham khảo và cư xử như một Box trong chức năng đó (nhìn từ bên ngoài, chứ không phải trong nội bộ, tất nhiên).

Tôi nghi ngờ rằng Rc s thực sự nhanh hơn tôi nghĩ.

PS: Khi nói về "nhanh", tôi có nghĩa là cả hội nghị và phân bổ/deallocating.

+2

Như thường lệ với các câu hỏi về hiệu suất, cách duy nhất để biết là lập hồ sơ tại chỗ. Micro-điểm chuẩn không phù hợp. –

Trả lời

7

Rc<T> rất, rất rẻ. Nó không phải là rẻ như T bởi khá một chút (giá trị đấm bốc là tương đối đắt tiền trong các thuật ngữ tối ưu hóa vi mô), nhưng ít hiệu quả hơn Box<T>.

Nó giống như Box, nhưng với một cặp vợ chồng thêm lời cho tội tham khảo mạnh mẽ và yếu đuối, và điều duy nhất mà cần phải chạm vào mà đang tạo một Rc (initialises các giá trị), nhân bản một Rc (gia số refcount) và thả một Rc (giảm số lần truy cập và chạy trình phá hủy nếu thích hợp). Trong mã không ổn định, cũng có thể hạ cấp xuống/nâng cấp từ Weak (những thứ tầm thường tương tự).

Dereferencing là thao tác bộ nhớ đơn giản giống như với Box.

7

Để trả lời câu hỏi của bạn, bạn có thể chuyển sang test thùng, trong đó có một giải pháp test (điều này cần một đêm):

#![feature(test)] 
extern crate test; 

use std::rc::Rc; 

fn test_with_box() { 
    let b = Box::new(1.0); 
    test::black_box(*b * 2.0); 
} 

fn test_with_rc() { 
    let rc = Rc::new(1.0); 
    test::black_box(*rc * 2.0); 
} 

#[bench] 
fn bench_box(b: &mut test::Bencher) { 
    b.iter(test_with_box) 
} 

#[bench] 
fn bench_rc(b: &mut test::Bencher) { 
    b.iter(test_with_rc) 
} 

Bây giờ biên soạn & chạy này:

$ rustc --test -O rc.rs && ./rc --bench 

running 2 tests 
test bench_box ... bench:   22 ns/iter (+/- 0) 
test bench_rc ... bench:   22 ns/iter (+/- 0) 

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured 

gì đã xảy ra? RC dường như đã được biên soạn hoàn toàn. Vì nó phải được, bởi vì chúng tôi đã không nhân bản nó. Vì vậy, việc thay đổi tương ứng fn tới:

fn test_with_rc() { 
    let rc = Rc::new(1.0); 
    test::black_box(*rc.clone() * 2.0); 
} 

Chúng tôi nhận được như sau:

running 2 tests 
test bench_box ... bench:   23 ns/iter (+/- 1) 
test bench_rc ... bench:   25 ns/iter (+/- 1) 

test result: ok. 0 passed; 0 failed; 0 ignored; 2 measured 

Vì vậy, đủ để nói, có thể bạn sẽ cần phải lo lắng về những thứ khác trước khi nhìn vào overhead RC gây ra.

+0

* RC dường như đã được biên soạn hoàn toàn * Tôi không nghĩ rằng bạn có thể tuyên bố rằng nó được tối ưu hóa. Nếu bạn nhìn vào [LLVM IR] (http://is.gd/AB68e3), bạn có thể thấy rằng 'test_with_box' gọi' @je_mallocx (i64 8, i32 0) 'và' test_with_rc' gọi '@je_mallocx (i64 24, i32 0) ', do đó, hai khối sẽ không được lắp ráp giống nhau. Ngoài ra còn có thêm 4 hướng dẫn cho trường hợp 'Rc'. – Shepmaster

Các vấn đề liên quan