阿里妹導讀:我們在選擇一種開發語言時會綜合考量各方面的特性,根據實際的需求適當取捨。魚和熊掌往往不可兼得,要想開發效率高,必然要犧牲效能和資源消耗,反之亦然。但是Rust卻出其不意,令人眼前一亮!本文將從效能、記憶體安全、開發效率、跨平臺性及生態等五個方面,對Rust這一程式語言進行一些科普性質的分享。
rust | c++ | golang | python |
249KB | 129KB | 1577KB | 3880KB |
結論:(二進位制大小)python > golang > rust > c++
rust | c++ | golang | python | |
第一次 | 850 | 776 | 378 | 30 |
第二次 | 859 | 782 | 797 | 30 |
第三次 | 857 | 777 | 391 | 30 |
第四次 | 827 | 740 | 684 | 31 |
結論:(執行效率)rust > c++ > golang > python
rust | c++ | golang | python |
30M | 22M | 124M | 190M |
結論:(記憶體消耗) python > golang > rust > c++
rust | c++ | golang | python |
12.5% | 12.5% | 24 | 13 |
結論:(CPU消耗)golang > python > rust = c++
let obj = String::from("hello");
fn main() {
let s = String::from("hello");
let s1 = s; //所有權發生了轉移,由s轉移給s1
print!("{}",s); //s無效,不能訪問,此句編譯會報錯
}
fn test(s1:String){
print!("{}",s1);
}
fn main() {
let s = String::from("hello");
test(s); //傳參,所有權發生了轉移
print!("{}",s); //此處s無效,編譯報錯
}
fn test(s1:&String){
print!("{}",s1);
}
fn main() {
let s = String::from("hello");
test(&s); //傳參,注意只是傳遞了引用,所有權還歸屬於s
print!("{}",s); //此處s依然有效,可以訪問
}
fn main() {
let s = String::from("hello");
let s1 = &s; //s1借用s,所有權還歸屬於s
print!("{}",s); //此處s依然有效,可以訪問
print!("{}",s1); //此處s1和s指向同一個物件
}
fn main() {
let s = String::from("hello");
change(&s);
}
fn change(some_string: &String) {
some_string.push_str(", world");
}
error[E0596]: cannot borrow immutable borrowed content `*some_string` as mutable
--> error.rs:8:5
|
7 | fn change(some_string: &String) {
| ------- use `&mut String` here to make mutable
8 | some_string.push_str(", world");
| ^^^^^^^^^^^ cannot borrow as mutable
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
error[E0499]: cannot borrow `s` as mutable more than once at a time
--> borrow_twice.rs:5:19
|
4 | let r1 = &mut s;
| - first mutable borrow occurs here
5 | let r2 = &mut s;
| ^ second mutable borrow occurs here
6 | }
| - first borrow ends here
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
error[E0106]: missing lifetime specifier
--> dangle.rs:5:16
|
5 | fn dangle() -> &String {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is
no value for it to be borrowed from
= help: consider giving it a 'static lifetime
一個可變引用。
任意數量的不可變引用。
error[E0106]: missing lifetime specifier
--> dangle.rs:5:16
|
5 | fn dangle() -> &String {
| ^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is
no value for it to be borrowed from
= help: consider giving it a 'static lifetime
error: `x` does not live long enough
|
6 | r = &x;
| - borrow occurs here
7 | }
| ^ `x` dropped here while still borrowed
...
10 | }
| - borrowed value needs to live until here
{
let r; // -------+-- 'a
// |
{ // |
let x = 5; // -+-----+-- 'b
r = &x; // | |
} // -+ |
// |
println!("r: {}", r); // |
} // -------+
兩個或更多指標同時訪問同一資料。
至少有一個這樣的指標被用來寫入資料。
不存在同步資料訪問的機制。
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
});
handle.join().unwrap();
}
error[E0373]: closure may outlive the current function, but it borrows `v`,
which is owned by the current function
--> src/main.rs:6:32
|
6 | let handle = thread::spawn(|| {
| ^^ may outlive borrowed value `v`
7 | println!("Here's a vector: {:?}", v);
| - `v` is borrowed here
|
help: to force the closure to take ownership of `v` (and any other referenced
variables), use the `move` keyword
|
6 | let handle = thread::spawn(move || {
| ^^^^^^^
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(|| {
println!("Here's a vector: {:?}", v);
});
drop(v); // 強制釋放變數v
handle.join().unwrap();
}
help: to force the closure to take ownership of `v` (and any other referenced
variables), use the `move` keyword
|
6 | let handle = thread::spawn(move || {
use std::thread;
fn main() {
let v = vec![1, 2, 3];
let handle = thread::spawn(move || { //使用 move 關鍵字強制獲取它使用的值的所有權,接下來就可以正常使用v了
println!("Here's a vector: {:?}", v);
});
handle.join().unwrap();
}
use std::thread;
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}
use std::thread;
use std::sync::mpsc;
fn main() {
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
println!("val is {}", val);//在這裡會發生編譯錯誤
});
let received = rx.recv().unwrap();
println!("Got: {}", received);
}
error[E0382]: use of moved value: `val`
--> src/main.rs:10:31
|
9 | tx.send(val).unwrap();
| --- value moved here
10 | println!("val is {}", val);
| ^^^ value used here after move
|
= note: move occurs because `val` has type `std::string::String`, which does
not implement the `Copy` trait
use std::sync::Mutex;
use std::thread;
fn main() {
let counter = Mutex::new(0);
let mut handles = vec![];
for _ in 0..10 {
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
error[E0382]: capture of moved value: `counter`
--> src/main.rs:10:27
|
9 | let handle = thread::spawn(move || {
| ------- value moved (into closure) here
10 | let mut num = counter.lock().unwrap();
| ^^^^^^^ value captured here after move
|
= note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
which does not implement the `Copy` trait
error[E0382]: use of moved value: `counter`
--> src/main.rs:21:29
|
9 | let handle = thread::spawn(move || {
| ------- value moved (into closure) here
...
21 | println!("Result: {}", *counter.lock().unwrap());
| ^^^^^^^ value used here after move
|
= note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
which does not implement the `Copy` trait
error: aborting due to 2 previous errors
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
let handle2 = thread::spawn(move || {
let mut num2 = counter.lock().unwrap();
*num2 += 1;
});
handles.push(handle2);
error[E0382]: capture of moved value: `counter`
--> src/main.rs:16:24
|
8 | let handle = thread::spawn(move || {
| ------- value moved (into closure) here
...
16 | let mut num2 = counter.lock().unwrap();
| ^^^^^^^ value captured here after move
|
= note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
which does not implement the `Copy` trait
error[E0382]: use of moved value: `counter`
--> src/main.rs:26:29
|
8 | let handle = thread::spawn(move || {
| ------- value moved (into closure) here
...
26 | println!("Result: {}", *counter.lock().unwrap());
| ^^^^^^^ value used here after move
|
= note: move occurs because `counter` has type `std::sync::Mutex<i32>`,
which does not implement the `Copy` trait
error: aborting due to 2 previous errors
use std::rc::Rc;
use std::sync::Mutex;
use std::thread;
fn main() {
let counter = Rc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Rc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
error[E0277]: the trait bound `std::rc::Rc<std::sync::Mutex<i32>>:
std::marker::Send` is not satisfied in `[closure@src/main.rs:11:36:
15:10
counter:std::rc::Rc<std::sync::Mutex<i32>>]`
--> src/main.rs:11:22
|
11 | let handle = thread::spawn(move || {
| ^^^^^^^^^^^^^ `std::rc::Rc<std::sync::Mutex<i32>>`
cannot be sent between threads safely
|
= help: within `[closure@src/main.rs:11:36: 15:10
counter:std::rc::Rc<std::sync::Mutex<i32>>]`, the trait `std::marker::Send` is
not implemented for `std::rc::Rc<std::sync::Mutex<i32>>`
= note: required because it appears within the type
`[closure@src/main.rs:11:36: 15:10
counter:std::rc::Rc<std::sync::Mutex<i32>>]`
= note: required by `std::thread::spawn`
use std::sync::{Mutex, Arc};
use std::thread;
fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", *counter.lock().unwrap());
}
相關連結 [1]https://github.com/famzah/langs-performance [2]https://benchmarksgameteam.pages.debian.net/benchmarksgame/fastest/rust-gpp.html [3]https://deavid.wordpress.com/2019/10/12/benchmarking-python-vs-pypy-vs-go-vs-rust/ [4]https://www.chromium.org/Home/chromium-security/memory-safetyhttps://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/ [5]https://www.bookstack.cn/read/trpl-zh-cn/src-ch10-03-lifetime-syntax.md [6]https://github.com/redox-os/redox [7]https://stackoverflow.blog/2020/06/05/why-the-developers-who-use-rust-love-it-so-much/ [8]https://blog.discord.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f