1 回答
TA贡献1893条经验 获得超10个赞
不是直接的答案,而是一些背景以及其他人在评论中所说的内容。
包装文件和套接字的 Go 类型在任何意义上都相对较薄,Read()
并且Write()
对它们进行调用会导致执行系统调用(对于套接字,它更棘手,因为它们通过系统提供的轮询器使用异步 I/O,例如epoll
,kqueue
等IOCP
)。这意味着按 1 字节的块从文件或网络中读取是非常无效的。
考虑另一个极端,可以分配一个 100MiB 的缓冲区并尝试将其传递给Read()
. 虽然内核的系统调用很乐意接受该大小的目标,但应该注意的是,当代操作系统在大小约为 64KiB 1Read()
的网络套接字上具有内部缓冲区,因此在大多数情况下,您的调用将返回读取的数据量或更少。这意味着您将浪费大部分缓冲空间。
现在出现了另一组考虑因素:您的应用程序从套接字读取数据的模式是什么?
比如说,当您将数据从套接字流式传输到打开的文件时,您并不真正关心缓冲(您希望其他人决定选择“正确”的大小)。对于这种情况,只需使用io.Copy()
(目前(Go 1.6)使用 32KiB 的内部缓冲区)。
相反,如果您正在解析一些使用 TCP 作为其传输的应用程序级协议,您通常需要以任意固定大小的块读取数据。对于这种情况,最好的模式是将套接字包装在一个bufio.Reader
- 以解决上面概述的“小读取”问题 - 然后用于io.ReadFull()
将数据读取到您需要大小的本地数组/切片中(如果可能,请重用您的数组和切片以降低垃圾收集器的压力)。
另一种情况是基于文本的“逐行”协议,例如SMTP
or HTTP
。在这些协议中,最大行长度通常是固定的,因此使用协议行的最大大小的缓冲区来处理它们是有意义的。(但无论如何,要处理这样的协议,最好使用net/textproto
标准包。)
至于你的问题本身,我的观点是 512 只是一个没有特殊含义的美丽数字。当你写这样一本书时,无论如何你都必须选择一些价值。
从我对从网络读取的实际工作模式的描述中可以看出,大多数时候你根本没有处理缓冲的事务——让标准工具为你做这件事。当您遇到标准包提供的默认值的真正问题时,您应该只考虑调整这些东西。
TL; 博士
您正在阅读的书只是向您解释了基本概念,因此必须使用一些数字。
实际代码在需要缓冲时似乎使用其他数字(通常更高)......
……但除非绝对必要,否则您不应该关心这些数字:尽可能使用现成的工具。
1当然,我不能说所有操作系统,它们有不同的旋钮来调整这些东西,而且“当代”可能在一年或更短的时间内开始意味着不同的东西,你知道……我仍然认为我的估计是非常接近真相。
- 1 回答
- 0 关注
- 168 浏览
添加回答
举报