Golang中io.Pipe()创建的管道会分配多少内存?

Golang中io.Pipe()创建的管道会分配多少内存? 管道创建了一个同步的内存管道,返回管道读取器和写入器,使得读写操作可以并行进行。
以下是相关文档:
https://golang.org/pkg/io/#Pipe

但我没有找到关于管道内存消耗的详细信息。

3 回复

好的。

更多关于Golang中io.Pipe()创建的管道会分配多少内存?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


io.Pipe() 有以下实现

func Pipe() (*PipeReader, *PipeWriter) {
	p := &pipe{
		wrCh: make(chan []byte),
		rdCh: make(chan int),
		done: make(chan struct{}),
	}
	return &PipeReader{p}, &PipeWriter{p}
}

io.pipe 类型很简单

type pipe struct {
	wrMu sync.Mutex // Serializes Write operations
	wrCh chan []byte
	rdCh chan int

	once sync.Once // Protects closing done
	done chan struct{}
	rerr atomicError
	werr atomicError
}

到目前为止,没有分配太多内存。

在Go语言中,io.Pipe() 创建的管道是一个同步的内存管道,其内存分配主要取决于管道缓冲区的大小。根据Go标准库的实现,管道使用了一个固定大小的内部缓冲区来暂存数据。

具体来说,io.Pipe() 返回的管道内部缓冲区默认大小为 64KB(即 65,536 字节)。这个缓冲区用于在读取器和写入器之间传递数据,确保读写操作可以并行执行而不会阻塞,除非缓冲区满(写入时)或空(读取时)。当数据写入超过缓冲区大小时,写入操作会阻塞,直到读取器读取部分数据释放空间;同样,如果缓冲区为空,读取操作会阻塞,直到写入器写入新数据。

以下是一个简单示例,展示如何使用 io.Pipe() 并观察其行为:

package main

import (
    "fmt"
    "io"
    "time"
)

func main() {
    r, w := io.Pipe()

    // 启动一个goroutine进行写入
    go func() {
        defer w.Close()
        data := make([]byte, 1024) // 1KB数据
        for i := 0; i < 100; i++ { // 尝试写入100KB数据
            n, err := w.Write(data)
            if err != nil {
                fmt.Printf("Write error: %v\n", err)
                return
            }
            fmt.Printf("Written %d bytes, total: %d KB\n", n, (i+1))
            time.Sleep(10 * time.Millisecond) // 模拟延迟
        }
    }()

    // 在主goroutine中进行读取
    buf := make([]byte, 512) // 每次读取512字节
    totalRead := 0
    for {
        n, err := r.Read(buf)
        if err != nil {
            if err == io.EOF {
                fmt.Println("Read reached EOF")
                break
            }
            fmt.Printf("Read error: %v\n", err)
            break
        }
        totalRead += n
        fmt.Printf("Read %d bytes, total read: %d KB\n", n, totalRead/1024)
        time.Sleep(20 * time.Millisecond) // 模拟较慢的读取
    }
}

在这个示例中,写入器尝试以1KB的块写入数据,而读取器以512字节的块读取数据。由于管道缓冲区大小为64KB,如果写入速度超过读取速度,写入操作会在缓冲区满时阻塞,直到读取器消费数据。这演示了管道的同步机制和内存使用情况。

总结:io.Pipe() 分配的内存固定为约64KB的缓冲区。实际内存消耗不会超过这个大小,因为管道设计为流式处理,数据被及时传递而不长期驻留。如果应用需要更大缓冲区,可能需要自定义实现或使用其他同步机制。

回到顶部