Skip to content

Commit

Permalink
docs(异步):pin 说明
Browse files Browse the repository at this point in the history
  • Loading branch information
Danny5487401 committed Dec 2, 2024
1 parent f8bd8d2 commit de3e05c
Show file tree
Hide file tree
Showing 13 changed files with 262 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
- [3.1 静态分派 (static dispatching): 使用泛型函数](chapter06-type/src/type4-child.rs)
- [3.2 动态分派 (dynamic dispatching): 使用 trait object](chapter06-type/src/type5-dynamic-dispatch.rs)
- [4 AsRef 类型转换](chapter06-type/src/type6-asref.rs)
- [5 Deref解引用运算符(*)的重载:直接访问 Vec<T> 的方法](chapter06-type/src/type7-deref.rs)
- [5 Deref解引用运算符(*)的重载:直接访问内部元素的方法](chapter06-type/src/type7-deref.rs)

## [第七章:指针](chapter07-pointer/pointer.md)

Expand All @@ -84,7 +84,7 @@

## [第九章:hash](chapter09-hash/hash.md)

- [1 hashmap cap 扩容和缩容](chapter09-hash/src/hash1-cap.rs)
- [1 hashmap cap 扩容和缩容](chapter09-hash/src/hash1-hashmap.rs)
- [2 HashSet](chapter09-hash/src/hash2-hashset.rs)
- [3 BTreeMap](chapter09-hash/src/hash3-btreemap.rs)

Expand Down
45 changes: 40 additions & 5 deletions chapter07-pointer/pointer.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,49 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*

- [智能指针](#%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88)
- [COW 写时克隆(Clone on write)的智能指针](#cow-%E5%86%99%E6%97%B6%E5%85%8B%E9%9A%86clone-on-write%E7%9A%84%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88)
- [Cow的使用场景](#cow%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)
- [MutexGuard](#mutexguard)
- [指针](#%E6%8C%87%E9%92%88)
- [共享引用指针 Shared references (&)](#%E5%85%B1%E4%BA%AB%E5%BC%95%E7%94%A8%E6%8C%87%E9%92%88-shared-references-)
- [可变引用指针 Mutable references (&mut)](#%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8%E6%8C%87%E9%92%88-mutable-references-mut)
- [裸指针 Raw pointers (*const and *mut)](#%E8%A3%B8%E6%8C%87%E9%92%88-raw-pointers-const-and-mut)
- [智能指针 Smart Pointers](#%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88-smart-pointers)
- [COW 写时克隆(Clone on write)的智能指针](#cow-%E5%86%99%E6%97%B6%E5%85%8B%E9%9A%86clone-on-write%E7%9A%84%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88)
- [Cow的使用场景](#cow%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF)
- [MutexGuard](#mutexguard)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## 智能指针
# 指针

## 共享引用指针 Shared references (&)

- 共享引用指针指向的是一个值的内存地址;
- 当一个值存在共享引用指针的时候,同时也阻止了这个值的可变;
- Interior mutability 是一个特例,允许内部值可变;
- 一个值可以存在任意个共享引用指针;
- 共享引用指针语法: &type 或 &'a type (带生命周期标记) ;
- 共享引用指针的复制是 "shallow" 操作,只复制指针自身,也就是说共享引用指针是可复制的;
- 释放共享引用指针对共享引用指针所指向的值没有影响;
- 如果共享引用指针指向的是一个临时值( temporary value) ,共享引用指针和临时值在当前域中共存;

## 可变引用指针 Mutable references (&mut)

- 可变引用指针同样指向的是一个值的内存地址;
- 可变引用指针语法: &mut type or &'a mut type;
- 一个值的可变引用指针是访问这个值的唯一途径,所以可变引用指针不可以复制;

## 裸指针 Raw pointers (*const and *mut)

- 裸指针没有安全保证和值的有效性保证;
- 裸指针语法: *const T 或 *mut T,例如 *const i32 代表 对一个 32-bit 整数值的裸指针;
- 裸指针的复制和释放操作对它所指向的值的生命没有影响;
- 对裸指针的解引用操作 (&* or &mut *)是不安全操作( unsafe operation);
- 对裸指针的解引用操作 (&* or &mut *)可以把一个裸指针转成共享引用或可变引用;
- 裸指针通常是不鼓励使用;
- 使用裸指针的场景有三种:为了方便 Rust 和其他语言的交互;对性能有更好要求的函数;实现底层函数。
- 当比较裸指针的时候,比较的是地址值、并不是对裸指针指向的值做比较;
- 当比较指向DST类型值的裸指针的时候,除了比较地址值,还同时比较辅助值;

## 智能指针 Smart Pointers

在 Rust 中,凡是需要做资源回收的数据结构,且实现了 Deref/DerefMut/Drop,都是智能指针。

Expand Down
2 changes: 1 addition & 1 deletion chapter09-hash/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors.workspace = true

[[bin]]
name = "hash1"
path = "src/hash1-cap.rs"
path = "src/hash1-hashmap.rs"


[[bin]]
Expand Down
Binary file added chapter09-hash/ctrl_table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added chapter09-hash/find_ele_process.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 95 additions & 4 deletions chapter09-hash/hash.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,63 @@
- [结构](#%E7%BB%93%E6%9E%84)
- [扩容和缩容](#%E6%89%A9%E5%AE%B9%E5%92%8C%E7%BC%A9%E5%AE%B9)
- [HashSet](#hashset)
- [BTreeMap](#btreemap)
- [BTreeSet](#btreeset)
- [参考](#%E5%8F%82%E8%80%83)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# hash

## hashMap

Rust 中 HashMap 采用的是开放寻址法处理冲突
> A hash map implemented with quadratic probing and SIMD lookup.
- 二次探查(quadratic probing): 理论上是在冲突发生时,不断探寻哈希位置加减 n 的二次方,找到空闲的位置插入
- SIMD 查表(SIMD lookup): SIMD 借助现代 CPU 单指令多数据集的能力,在rust 中, 通过一个指令可以将多个相关数据(16个 ctrl
bytes)加载到内存,大大提高了查表的速度。

### 结构

```rust
// 1.82.0-c55404ec682381aef0f0325c615d2e21ffe04092/library/std/src/collections/hash/map.rs

use hashbrown::hash_map as base;
use crate::hash::{BuildHasher, Hash, RandomState};

#[cfg_attr(not(test), rustc_diagnostic_item = "HashMap")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_insignificant_dtor]
pub struct HashMap<K, V, S = RandomState> {
base: base::HashMap<K, V, S>,
}

// src/hash/random.rs
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
#[derive(Clone)]
pub struct RandomState {
k0: u64,
k1: u64,
}

// 1.82.0-0f03adc482c497f86e341cd37c08bc292e2190c0/vendor/hashbrown/src/map.rs
pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) hash_builder: S,
pub(crate) table: RawTable<(K, V), A>,
}
```

HashMap 有三个泛型参数,K 和 V 代表 key/value 的类型,S 是哈希算法的状态,它默认是 RandomState,占两个 u64。
RandomState 使用 SipHash 作为缺省的哈希算法,它是一个加密安全的哈希函数(cryptographically secure hashing)

Rust 的 HashMap 复用了 hashbrown 的 HashMap。hashbrown 是 Rust 下对 Google Swiss Table 的一个改进版实现.

HashMap 里有两个域,一个是 hash_builder,类型是标准库使用的 RandomState,还有一个是具体的 RawTable

```rust

// 其中 T 是 (K, V),A 是内存分配器
pub struct RawTable<T, A: Allocator = Global> {
table: RawTableInner,
alloc: A,
Expand All @@ -39,17 +79,35 @@ struct RawTableInner {

// [Padding], T1, T2, ..., Tlast, C1, C2, ...
// ^ points here
// 指向堆内存哈希表末端的 ctrl
// 指向堆内存哈希表末端的 ctrl 区的指针
ctrl: NonNull<u8>,

// Number of elements that can be inserted before we need to grow the table
// 下次扩容前,还能插入的数量
growth_left: usize,

// Number of elements in the table, only really used by len()
// 哈希表中元素数量
items: usize,
}
```

ctrl 表的主要目的是快速查找.

![img.png](ctrl_table.png)

一张 ctrl 表里,有若干个 128bit 或者说 16 个字节的分组(group),group 里的每个字节叫 ctrl byte,对应一个 bucket,那么一个
group 对应 16 个 bucket。如果一个 bucket 对应的 ctrl byte 首位不为 1,就表示这个 ctrl byte 被使用;如果所有位都是
1,或者说这个字节是 0xff,那么它是空闲的.

现在要查找 key 为 ‘c’ 的数据:
![img.png](find_ele_process.png)

1. 首先对 ‘c’ 做哈希,得到一个哈希值 h;
2. 把 h 跟 bucket_mask 做与,得到一个值,图中是 139;
3. 拿着这个 139,找到对应的 ctrl group 的起始位置,因为 ctrl group 以 16 为一组,所以这里找到 128;
4. 用 SIMD 指令加载从 128 对应地址开始的 16 个字节;
5. 对 hash 取头 7 个 bit,然后和刚刚取出的 16 个字节一起做与,找到对应的匹配,如果找到了,它(们)很大概率是要找的值;
6. 如果不是,那么以二次探查(以 16 的倍数不断累积)的方式往后查找,直到找到为止。

### 扩容和缩容

当 HashMap::new() 时,它并没有分配空间,容量为零,随着哈希表不断插入数据,它会以 2 的幂减一的方式增长,最小是3。
Expand Down Expand Up @@ -103,9 +161,42 @@ where

## HashSet

HashSet 是 HashMap 的简化版本,底层实现是 HashMap<K, ()>。

```rust
pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator = Global> {
pub(crate) map: HashMap<T, (), S, A>,
}

```
```

## BTreeMap

BTreeMap 是在 HashMap 的基础上,增加了有序性,它会按照 key 的升序来存储、便利内部元素。

```rust
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")]
#[rustc_insignificant_dtor]
pub struct BTreeMap<
K,
V,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global,
> {
root: Option<Root<K, V>>,
length: usize,
/// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes).
pub(super) alloc: ManuallyDrop<A>,
// For dropck; the `Box` avoids making the `Unpin` impl more strict than before
_marker: PhantomData<crate::boxed::Box<(K, V), A>>,
}

```

## BTreeSet

BTreeSet 是 BTreeMap 的简化版本,可用来表示有序集合。

## 参考

- [rust 哈希表](https://juejin.cn/post/7134717280214056990)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ fn main() {
let mut map = HashMap::new();
explain("empty", &map);

// 插入元素
map.insert("a", 1);
explain("added 1", &map);

Expand All @@ -18,16 +19,27 @@ fn main() {
assert_eq!(map.get(&"a"), Some(&1));
assert_eq!(map.get_key_value(&"b"), Some((&"b", &2)));

// 移除元素
map.remove(&"a"); // 删除后就找不到了
assert_eq!(map.contains_key(&"a"), false);
assert_eq!(map.get(&"a"), None);
explain("removed", &map);

// shrink 后哈希表变小
// shrink 缩小哈希表占用的内存空间
map.shrink_to_fit();
explain("shrinked", &map);
explain("shrink", &map);
}

fn explain<K, V>(name: &str, map: &HashMap<K, V>) {
println!("{}:len:{},cap:{}", name, map.len(), map.capacity())
}

/*
empty:len:0,cap:0
added 1:len:1,cap:3
added 3:len:3,cap:3
added 4:len:4,cap:7
removed:len:3,cap:7
shrink:len:3,cap:3
*/
2 changes: 1 addition & 1 deletion chapter09-hash/src/hash3-btreemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn main() {
let map = explain("remove 1", map);

for item in map.iter() {
println!("{:?}", item);
println!("{:?}", item); // 有序
}
}

Expand Down
5 changes: 5 additions & 0 deletions chapter14-concurrecy/concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- [基于 Send 和 Sync 的线程安全](#%E5%9F%BA%E4%BA%8E-send-%E5%92%8C-sync-%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8)
- [线程同步](#%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5)
- [同步 trait vs 异步 trait](#%E5%90%8C%E6%AD%A5-trait-vs-%E5%BC%82%E6%AD%A5-trait)
- [异步运行时](#%E5%BC%82%E6%AD%A5%E8%BF%90%E8%A1%8C%E6%97%B6)
- [executor](#executor)

Expand All @@ -28,6 +29,10 @@ Send和Sync是 Rust 安全并发的重中之重,但是实际上它们只是标
- oneshot
- Actor

## 同步 trait vs 异步 trait

![img.png](sync-vs-async-trait.png)

## 异步运行时

- reactor 会利用操作系统提供的异步 I/O,比如 epoll / kqueue / IOCP,来监听操作系统提供的 IO 事件,当遇到满足条件的事件时,就会调用
Expand Down
Loading

0 comments on commit de3e05c

Please sign in to comment.