story
在项目中的数据库链接使用socket链接,原来socket链接默认的buffer只有1460byte,从db读取大背包数据时候就会变得很慢,主要原因在buffer设置很小时候,socket进程会收到多个info消息,多次处理消耗时间。
后面把buffer从原来的1460设置到65535({recbuf 65535})后,db读取7m的数据由原来的6.2s提升到0.22s左右。
recbuf sndbuf buffer 之间关系
概念
- recbuf 系统层面的接收区缓存
- sndbuf 系统层面的发送缓冲区
- buffer erlang虚拟机层面的接收缓冲区,有高速的内存分配器,默认1460
测试三者设置后的现象
系统环境
CentOS Linux release 7.8.2003 (Core)
OTP22
系统默认设置:1
2
3
4[root@localhost sbin]# cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 6291456
[root@localhost sbin]# cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4194304
默认的三者数值
1 | Eshell V10.5 (abort with ^G) |
单独设置recbuf
recbuf自动x2(可能考虑到封包的大小),buffer自动设置为目标值1
2
3
4
5Eshell V10.5 (abort with ^G)
"www.baidu.com", 80, [{recbuf, 2000},{active,false}]). {ok, S} = gen_tcp:connect(
{ok,#Port<0.6>}
inet:getopts(S, [recbuf,sndbuf,buffer]).
{ok,[{recbuf,4000},{sndbuf,87040},{buffer,2000}]}
单独设置sndbuf
自动x21
2
3
4"www.baidu.com", 80, [{sndbuf, 4096},{active,false}]). {ok, S1} = gen_tcp:connect(
{ok,#Port<0.7>}
inet:getopts(S1, [recbuf,sndbuf,buffer]).
{ok,[{recbuf,369280},{sndbuf,8192},{buffer,1460}]}
单独设置buffer
只生效buffer部分1
2
3
4"www.baidu.com", 80, [{buffer, 4096},{active,false}]). {ok, S2} = gen_tcp:connect(
{ok,#Port<0.8>}
inet:getopts(S2, [recbuf,sndbuf,buffer]).
{ok,[{recbuf,369280},{sndbuf,87040},{buffer,4096}]}
三者之间更详细的说明以及源码解读可参考:
gen_tcp接收缓冲区易混淆概念纠正