Merge pull request #24 from sunface/main

sync
pull/1126/head
Rustln 2 years ago committed by GitHub
commit 4dbf79b1a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,7 +8,7 @@
高级语言 Python/Java 等往往会弱化堆栈的概念,但是要用好 C/C++/Rust就必须对堆栈有深入的了解原因是两者的内存管理方式不同前者有 GC 垃圾回收机制,因此无需你去关心内存的细节。
栈内存从高位地址向下增长,且栈内存是连续分配的,一般来说**操作系统对栈内存的大小都有限制**,因此 C 语言中无法创建任意长度的数组。在 Rust 中,`main` 线程的[栈大小是 `8MB`](https://course.rs/pitfalls/stack-overflow.html),普通线程是 `2MB`,在函数调用时会在其中创建一个临时栈空间,调用结束后 Rust 会让这个栈空间里的对象自动进入 `Drop` 流程,最后栈顶指针自动移动到上一个调用栈顶,无需程序员手动干预,因而栈内存申请和释放是非常高效的。
栈内存从高位地址向下增长,且栈内存是连续分配的,一般来说**操作系统对栈内存的大小都有限制**,因此 C 语言中无法创建任意长度的数组。在 Rust 中,`main` 线程的[栈大小是 `8MB`](https://course.rs/compiler/pitfalls/stack-overflow.html),普通线程是 `2MB`,在函数调用时会在其中创建一个临时栈空间,调用结束后 Rust 会让这个栈空间里的对象自动进入 `Drop` 流程,最后栈顶指针自动移动到上一个调用栈顶,无需程序员手动干预,因而栈内存申请和释放是非常高效的。
与栈相反,堆上内存则是从低位地址向上增长,**堆内存通常只受物理内存限制**,而且通常是不连续的,因此从性能的角度看,栈往往比堆更高。

@ -54,7 +54,7 @@
总之,`async`编程并没有比多线程更好,最终还是根据你的使用场景作出合适的选择,如果无需高并发,或者也不在意线程切换带来的性能损耗,那么多线程使用起来会简单、方便的多!最后再简单总结下:
> 若大家使用 tokio那 CPU 密集的任务尤其需要用线程的方式去处理,例如使用 `spawn_blocking` 创建一个阻塞的线程完成相应 CPU 密集任务。
> 若大家使用 tokio那 CPU 密集的任务尤其需要用线程的方式去处理,例如使用 `spawn_blocking` 创建一个阻塞的线程完成相应 CPU 密集任务。
>
> 至于具体的原因不仅是上文说到的那些还有一个是tokio 是协作式地调度器,如果某个 CPU 密集的异步任务是通过 tokio 创建的那理论上来说该异步任务需要跟其它的异步任务交错执行最终大家都得到了执行皆大欢喜。但实际情况是CPU 密集的任务很可能会一直霸着着 CPU此时 tokio 的调度方式决定了该任务会一直被执行,这意味着,其它的异步任务无法得到执行的机会,最终这些任务都会因为得不到资源而饿死。
>

@ -184,7 +184,7 @@ let first_entry = array[0];
`array` 数组的底层数据隐藏在了重重封锁之后,那么编译器如何使用 `array[0]` 这种数组原生访问语法通过重重封锁,准确的访问到数组中的第一个元素?
1. 首先, `array[0]` 只是[`Index`](https://doc.rust-lang.org/std/ops/trait.Index.html)特征的语法糖:编译器会将 `array[0]` 转换为 `array.index(0)` 调用,当然在调用之前,编译器会先检查 `array` 是否实现了 `Index` 特征。
2. 接着,编译器检查 `Rc<Box<[T; 3]>>` 是否有实现 `Index` 特征,结果是否,不仅如此,`&Rc<Box<[T; 3]>>` 与 `&mut Rc<Box<[T; 3]>>` 也没有实现。
2. 接着,编译器检查 `Rc<Box<[T; 3]>>` 是否有实现 `Index` 特征,结果是否,不仅如此,`&Rc<Box<[T; 3]>>` 与 `&mut Rc<Box<[T; 3]>>` 也没有实现。
3. 上面的都不能工作,编译器开始对 `Rc<Box<[T; 3]>>` 进行解引用,把它转变成 `Box<[T; 3]>`
4. 此时继续对 `Box<[T; 3]>` 进行上面的操作 `Box<[T; 3]>` `&Box<[T; 3]>`,和 `&mut Box<[T; 3]>` 都没有实现 `Index` 特征,所以编译器开始对 `Box<[T; 3]>` 进行解引用,然后我们得到了 `[T; 3]`
5. `[T; 3]` 以及它的各种引用都没有实现 `Index` 索引(是不是很反直觉:D在直觉中数组都可以通过索引访问实际上只有数组切片才可以!),它也不能再进行解引用,因此编译器只能祭出最后的大杀器:将定长转为不定长,因此 `[T; 3]` 被转换成 `[T]`,也就是数组切片,它实现了 `Index` 特征,因此最终我们可以通过 `index` 方法访问到对应的元素。

@ -192,7 +192,7 @@ fn read_username_from_file() -> Result<String, io::Error> {
### 传播界的大明星: ?
大明星出场,必得有排面,来看看 `?` 的排面:
大明星出场,必得有排面,来看看 `?` 的排面:
```rust
use std::fs::File;

@ -154,7 +154,7 @@ fn main() {
let (a, b, c, d, e);
(a, b) = (1, 2);
// _ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有一个变量名而是使用了 _
// _ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有使用一个变量名而是使用了 _
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5 };

@ -2,7 +2,7 @@
依赖覆盖对于本地开发来说,是很常见的,大部分原因都是我们希望在某个包发布到 `crates.io` 之前使用它,例如:
- 你正在同时开发一个包和一个项目,而后者依赖于前者,你希望能在项目中对正在开发的包进行测试
- 你正在同时开发一个包和一个项目,而后者依赖于前者,你希望能在项目中对正在开发的包进行测试
- 你引入的一个依赖包在 `master` 分支发布了新的代码,恰好修复了某个 bug因此你希望能单独对该分支进行下测试
- 你即将发布一个包的新版本,为了确保新版本正常工作,你需要对其进行集成测试
- 你为项目的某个依赖包提了一个 PR 并解决了一个重要 bug在等待合并到 `master` 分支,但是时间不等人,因此你决定先使用自己修改的版本,等未来合并后,再继续使用官方版本

Loading…
Cancel
Save