Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Besbash committed Nov 27, 2024
1 parent 691340c commit b79d58f
Showing 1 changed file with 22 additions and 15 deletions.
37 changes: 22 additions & 15 deletions pkg/buffer/bufio/bufio(缓冲区读写-增强).md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

> 先弄明白源码库的大概原理,然后再进行修改。
**bufio.Reader 和 bufio.Writer:**
1)bufio.Reader

- bufio.Reader,相当于为某个Reader(fd)在读取操作时,增加了缓冲区(存放一次性Read的内容),从而减少**系统调用Read**的调用次数。
- bufio.Writer,相当于为某个Writer(fd)在写入操作时,增加了缓冲区(存放即将要Write的内容),从而减少**系统调用Write**的调用次数。
- 相当于为某个Reader(fd)在读取操作时,增加了缓冲区(存放一次性Read的内容),从而减少**系统调用Read**的调用次数。
- **类似于C语言的标准IO缓冲区:低级IO-缓冲区(fsync、延迟写).md**

2)bufio.Writer:

- 相当于为某个Writer(fd)在写入操作时,增加了缓冲区(存放即将要Write的内容),从而减少**系统调用Write**的调用次数。
- **类似于C语言的标准IO缓冲区:低级IO-缓冲区(fsync、延迟写).md**

## 1.1 Reader原理

> **数据流:bufio.Reader调用 Read => 底层Reader调用 Read => 保存到Reader的buf数组(预读到用户缓冲区) => 从buf中返回N个字节**
> **数据流:**
>
> **bufio.Reader调用 Read => 底层Reader调用 Read => 保存到Reader的buf数组(预读到用户缓冲区) => 从buf中返回N个字节**
~~~go
// Reader implements buffering for an io.Reader object.
Expand All @@ -23,21 +30,21 @@ type Reader struct {
}
~~~

1**字段说明:**
1**字段说明:**

- **buf**:bufio.Reader 底层使用的实际内存。
- **rd**:bufio.Reader 底层使用使用的Reader(fd)。

----

2**读取操作:** 参照[Reader.ReadByte函数](https://github.com/zhixunjie/im-fun/blob/584f7ec67b1140de3dcabc2bb6a73835421d0b9b/pkg/buffer/bufio/bufio.go#L258)的源码。
2**读取操作:** 参照[Reader.ReadByte函数](https://github.com/zhixunjie/im-fun/blob/584f7ec67b1140de3dcabc2bb6a73835421d0b9b/pkg/buffer/bufio/bufio.go#L258)的源码。

- 执行bufio.Reader的Read操作时:
- 如果发现缓冲区buf的内容不足以满足本次读取的字节数,会调用fill函数,从而调用底层Reader(fd)的Read(系统调用)函数,一次性读取N个字节。

- 等到从底层Reader(fd)读取完毕后,再把执行最后的copy操作。

3**读取过程中 r、w 值的变化过程**:执行读取操作,会增加r的值,执行写入操作,会增加w的值。
3**读取过程中 r、w 值的变化过程**:执行读取操作,会增加r的值,执行写入操作,会增加w的值。

- **w的值比r的值大**:说明还能从buf中读取操作。
- **w的值等于r的值**
Expand All @@ -61,18 +68,18 @@ type Writer struct {
}
~~~

大致跟Reader相同,参照[Writer.WriteByte函数](https://github.com/zhixunjie/im-fun/blob/584f7ec67b1140de3dcabc2bb6a73835421d0b9b/pkg/buffer/bufio/bufio.go#L687)的源码。
> 大致跟Reader相同,参照[Writer.WriteByte函数](https://github.com/zhixunjie/im-fun/blob/584f7ec67b1140de3dcabc2bb6a73835421d0b9b/pkg/buffer/bufio/bufio.go#L687)的源码。
- 特点是:
- 写入时,如果发现存放写入内容的缓冲区buf(用户缓冲区)空间不足时,会调用系统调用函数Write;
- 从而把用户缓冲区的内容刷入(Flush)到内核缓存区后,从而释放 buf(用户缓冲区)的内容以满足写入操作。
特点是:
- 写入时,如果发现存放写入内容的缓冲区buf(用户缓冲区)空间不足时,会调用系统调用函数Write;
- 从而把用户缓冲区的内容刷入(Flush)到内核缓存区后,从而释放 buf(用户缓冲区)的内容以满足写入操作。


# 2. 功能加强

> 源码来源:基于Go 1.18.10,这里为其 reader 和 writer 做能力加强
**1Reader.ReadBytesN()**:读取N个字节(bytes)。
**1Reader.ReadBytesN()**:读取N个字节(bytes)。

- 虽然[Reader.read函数](https://github.com/zhixunjie/im-fun/blob/584f7ec67b1140de3dcabc2bb6a73835421d0b9b/pkg/buffer/bufio/bufio.go#L207)也能读取N个字节的数据,但是它不保证读取的字节数一定是等于N个字节,可能会小于N个字节。
- 因此,扩展了一个函数ReadBytesN(),能够保证从Reader中一次性读取N个字节的数据。
Expand All @@ -85,7 +92,7 @@ func (b *Reader) ReadBytesN(buf []byte) error {
}
~~~

**2SetFdAndResetBuffer():**设置**底层IO对象(fd)**,然后设置**底层IO对象**在读写操作(Read/Write系统调用)时用到的用户缓冲区。
**2SetFdAndResetBuffer():**设置**底层IO对象(fd)**,然后设置**底层IO对象**在读写操作(Read/Write系统调用)时用到的用户缓冲区。

- 优化:
- 通过SetFdAndResetBuffer + Buffer Pool,能够在每条TCP链接中重复使用缓冲池子中的内存;
Expand All @@ -108,7 +115,7 @@ func (b *Writer) SetFdAndResetBuffer(w io.Writer, buf []byte) {
}
~~~

**3Reader.Pop()**:把Reader 的用户缓冲区的n个字节直接返回给用户。
**3Reader.Pop()**:把Reader 的用户缓冲区的n个字节直接返回给用户。

- 如果用户调用Reader.Read()执行读取操作时,需要先make一个byte数组,然后传入Read()函数进行读取操作。
- 但是,如果用户调用Reader.Pop()执行读取操作时,就不再需要传入一个byte数组,直接复用Reader本身的缓冲区内存即可。
Expand All @@ -129,7 +136,7 @@ func (b *Reader) Pop(n int) ([]byte, error) {
}
~~~

**4Writer.Peek()**:原理跟Reader.Pop()一样。
**4Writer.Peek()**:原理跟Reader.Pop()一样。

~~~go
// Peek 直接返回Writer的用户缓冲区的n个字节
Expand Down

0 comments on commit b79d58f

Please sign in to comment.