推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

提高 Linux 上 socket 性能

   2023-07-31 网络整理佚名1830
核心提示:write)跨越了用户空间应用程序与内核的边界。这个过程耗费的资源很高,因此调用次数越多,通过这个调用链进行的工作所需要的时间就越长,应用程序的性能也就越低。这样,您就可以最小化调用的次数,并可以实现更好的整体性能。虚拟文件系统中存在一些可调节的内核参数。的计算;为了实现更好的性能应该启用这个选项。为瓶颈链接带宽生成一个度量标准;可以用于协议的自动优化。

解决方案

您应该考虑的第一件事是 Nagle 算法满足要求。 由于该算法尝试组合数据以形成完整的 TCP 段,因此会引入一些延迟。 但这种算法可以最大限度地减少线路上发送的数据包数量,因此可以最大限度地减少网络拥塞问题。

但在需要最小化传输延迟的情况下,API 可以提供解决方案。 要禁用 Nagle 算法,您可以设置该选项,如清单 1 所示。

清单 1. 禁用 TCP 的 Nagle 算法

int sock, flag, ret;

sock = socket( AF_INET, SOCK_STREAM, 0 );

flag = 1;
ret = setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag) );
if (ret == -1) {
  printf("Couldn't setsockopt(TCP_NODELAY)\n");
  exit(-1);
}

提示:Samba 实验表明,从 ® 服务器上的 Samba 驱动器读取数据时,禁用 Nagle 算法几乎可以使读取性能提高一倍。

技巧 2. 最小化系统调用开销

每当您通过系统调用读取或写入数据时,您都在使用系统调用。 此调用(例如读或写)跨越了用户空间应用程序和内核之间的边界。 此外,在进入内核之前,您的调用将通过 C 库到达内核中的通用函数 (())。 从 () 开始,调用转到文件系统层,内核在该层确定它正在处理的设备类型。 最后,调用进入该层,数据在该层被读取或排队等待传输(这涉及数据的副本)。

这个过程表明,系统调用不仅是在应用程序和内核中操作,而且在应用程序和内核中经过了很多层次。 此过程是资源密集型的,因此调用越多,完成此调用链所需的时间就越长,应用程序的性能就越低。

由于我们无法避免这些系统调用,唯一的选择就是尽量减少它们的使用次数。 幸运的是,我们可以控制这个过程。

解决方案

向其中一个写入数据时,尽量一次写入所有数据,而不是执行多次写入操作。 对于读操作,最好传入可以支持的最大缓冲区,因为如果没有足够的数据,内核会尝试填充整个缓冲区(还需要保持TCP通知窗口打开)。 这样,您可以最大限度地减少调用次数并获得更好的整体性能。

相关视频推荐

Linux内核源码分析之协议栈源码

《Tcpip详解卷一》:150行代码开启协议栈实现章节

网络原理tcp/udp、网络编程epoll/、面试中严重的“八股文”

需要C/C++ Linux服务器架构师学习资料加采集(资料包括C/C++、Linux、技术、Nginx、、MySQL、Redis、、、ZK、流媒体、CDN、P2P、K8S、、TCP/IP、协程、DPDK等),免费分享

技巧 3. 调整 TCP 窗口的延迟

TCP 的性能取决于几个因素。 两个最重要的因素是链路带宽(link)(消息在网络上传输的速率)和往返时间(round-trip time)或RTT(发​​送消息和接收另一端响应之间的延迟) )。 这两个值决定了所谓的延迟(BDP)。

给定链路带宽和RTT,就可以计算出BDP的值,但这意味着什么呢? BDP 提供了一种简单的方法来计算理论上最佳的 TCP 缓冲区大小(其中数据排队等待传输并由应用程序接收)。 如果缓冲区太小,则 TCP 窗口无法完全打开,这会限制性能。 如果缓冲区太大,就会浪费宝贵的内存资源。 如果缓冲区大小设置得恰到好处,就可以充分利用可用带宽。 让我们看一个例子:

BDP = *RTT

如果应用程序通过 LAN 进行通信,RRT 为 50 毫秒,则 BDP 为:

* 0.050 秒 / 8 = 0.625MB = 625KB

注意:这里除以8将位转换为字节以进行通信。

因此,我们可以将TCP窗口设置为BDP或1.25MB。 但Linux 2.6上默认的TCP窗口大小为110KB,这将连接的带宽限制为2.2MBps,计算如下:

= // 0.050 = 2.2MBps

如果我们使用上面计算的窗口大小,我们得到的带宽为 12.5MBps,计算如下:

625KB / 0.050 = 12.5MBps

差异确实很大,并且可以提供更大的吞吐量。 现在您知道如何计算应用程序的最佳缓冲区大小。 但如何改变呢?

解决方案

该 API 提供了多个选项,其中两个可用于修改发送和接收缓冲区的大小。 清单 2 显示了如何使用 和 选项来调整发送和接收缓冲区的大小。

注意:虽然缓冲区的大小决定了通告的 TCP 窗口的大小,但 TCP 还在通告的窗口内维护了一个拥塞窗口。 因此,由于该拥塞窗口,给定节点可能永远不会利用最大的通告窗口。

清单 2. 手动设置发送和接收缓冲区大小

int ret, sock, sock_buf_size;
sock = socket( AF_INET, SOCK_STREAM, 0 );
sock_buf_size = BDP;
ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );
ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );

在Linux 2.6内核中,发送缓冲区的大小由调用用户定义,但接收缓冲区自动加倍。 您可以调用来验证每个缓冲区的大小。

巨帧(jumbo frame) 
我们还可以考虑将包的大小从 1,500 字节修改为 9,000 字节(称为巨帧)。在本地网络中可以通过设置最大传输单元(Maximum Transmit Unit,MTU)来设置巨帧,这可以极大地提高性能。

例如,TCP最初支持最大64KB的窗口(使用16位值来定义窗口大小)。 通过 (RFC 1323) 扩展,您可以使用 32 位值来表示窗口大小。 GNU/Linux 中提供的 TCP/IP 堆栈支持此选项(以及其他一些选项)。

提示:Linux 内核还包括自动优化这些缓冲区的功能(请参见下面的表 1),但这些选项会影响整个堆栈。 如果您只需要调整某个连接或某种连接类型的窗口大小,那么这种机制可能无法满足您的需求。

技巧 4. 动态优化 GNU/Linux TCP/IP 堆栈

标准 GNU/Linux 发行版尝试针对各种部署情况进行优化。 这意味着标准发行版可能没有专门针对您的环境进行优化。

解决方案

GNU/Linux 提供了许多可调的内核参数,您可以使用它们来动态配置操作系统以供您自己使用。 让我们看一下影响性能的一些更重要的选项。

/proc 虚拟文件系统中有一些可调的内核参数。 该文件系统中的每个文件代表一个或多个参数,可以使用 cat 工具读取或使用 echo 命令修改。 清单 3 显示了如何查询或启用可调参数(在本例中是在 TCP/IP 堆栈中启用 IP 转发)。

清单 3. 调整:在 TCP/IP 堆栈中启用 IP 转发

[root@camus]# cat /proc/sys/net/ipv4/ip_forward
0
[root@camus]# echo "1" > /poc/sys/net/ipv4/ip_forward
[root@camus]# cat /proc/sys/net/ipv4/ip_forward
1
[root@camus]#

表 1 显示了几个可帮助您提高 Linux TCP/IP 堆栈性能的可调参数。

可调参数

默认值

选项 说明

/proc/sys/net/核心/

””

定义默认接收窗口大小; 对于较大的 BDP,这个值应该更大。

/proc/sys/net/核心/

””

定义接收窗口的最大尺寸; 对于较大的 BDP,该大小也应该更大。

/proc/sys/net/核心/

””

定义默认发送窗口大小; 对于较大的 BDP,这个值应该更大。

/proc/sys/net/核心/

””

定义发送窗口的最大尺寸; 对于较大的 BDP,该大小也应该更大。

/proc/sys/net/ipv4/

“1”

按照 RFC 1323 的定义启用; 必须启用才能支持大于 64KB 的窗口。

/proc/sys/net/ipv4/

“1”

启用选择性确认 ( ),通过选择性地确认无序接收的数据包来提高性能(从而允许发送方仅发送丢失的段); (对于 WAN 通信)此选项应启用,但这会增加 CPU 使用率。

/proc/sys/net/ipv4/

“1”

启用前向确认( ),从而启用选择性确认(SACK)以减少拥塞; 还应启用此选项。

/proc/sys/net/ipv4/

“1”

能够以比重传超时更精确的方式计算 RTT(请参阅 RFC 1323); 应启用此选项以获得更好的性能。

/proc/sys/net/ipv4/

“24576 32768 49152”

确定 TCP 堆栈应如何反映内存使用情况; 每个值的单位是一个内存页(通常是

4KB)。 第一个值是内存使用量的下限。 第二个值是内存压力模式开始对缓冲区使用施加压力的上限。 第三个值是内存限制。在这个级别可以丢弃数据包,从而减少

使用更少的内存。 对于较大的 BDP,可以增加这些值(但请记住单位是内存页,而不是字节)。

/proc/sys/net/ipv4/

“4096 16384”

定义每个自动调整所使用的内存。 第一个值是分配给发送缓冲区的最小字节数。 第二个值是默认值(该值将被覆盖),当系统负载不重时,缓冲区可以增长到该值。 第三个值是发送缓冲区空间的最大字节数(该值将被覆盖)。

/proc/sys/net/ipv4/

“4096 87380”

与 类似,但它表示用于自动调节的接收缓冲区的值。

/proc/sys/net/ipv4/

“0”

允许TCP/IP堆栈适应高吞吐量下的低延迟; 应禁用此选项。

/proc/sys/net/ipv4/

“0”

启用发送方拥塞控制算法,该算法维护吞吐量估计并尝试优化整体带宽利用率; 应针对 WAN 流量启用此选项。

/proc/sys/net/ipv4/

“1”

启用快速长途网络; 这可以更好地利用以千兆位速度运行的链路; 应针对 WAN 流量启用此选项。

与任何调整工作一样,最好的方法就是不断尝试。 应用程序的行为、处理器的速度以及可用内存量都会影响这些参数对性能的影响。 在某些情况下,您认为有益的实际上可能有害(反之亦然)。 因此,我们需要对每个选项进行一一实验,并检查每个选项的结果。 换句话说,我们需要相信自己的经验,但要验证每一次修改。

提示:这里有一个关于持久化配置的问题。 请注意,如果您重新启动 GNU/Linux 系统,您需要的任何可调内核参数都将恢复为其默认值。 要将您设置的值用作这些参数的默认值,您可以使用/etc/.conf 将这些参数配置为您在系统启动时设置的值。

GNU/Linux 工具

GNU/Linux 对我来说非常有吸引力,因为它有很多可用的工具。 尽管其中大多数是命令行工具,但它们都非常有用且直观。 GNU/Linux 提供了多种工具(一些 GNU/Linux 本身、一些开源软件)用于调试网络应用程序、测量带宽/吞吐量以及检查链路使用情况。

表 2 列出了一些最有用的 GNU/Linux 工具及其用途。 表 3 列出了 GNU/Linux 发行版未提供的几个有用工具。 。

GNU/Linux 工具

使用

这是用于检查主机可用性的最常用工具,但也可用于识别由带宽延迟乘积计算的 RTT。

打印到网络主机的连接所采取的路径(路由),包括一系列路由器和网关,从而确定每一跳之间的延迟。

确定有关网络子系统、协议和连接的各种统计数据。

显示一个或多个连接的协议级数据包跟踪信息; 还包括计时信息,您可以使用它来研究不同协议服务的数据包计时。

GNU/Linux 工具

使用

为应用程序提供一些有关网络性能的信息。

生成瓶颈链路带宽的指标; 可用于协议的自动优化。

(数据包跟踪)功能通过易于使用的图形界面提供。

iperf

测量 TCP 和 UDP 网络性能; 测量最大带宽,并报告延迟和数据报丢失。

结论

尝试使用本文中介绍的提示和技术来提高应用程序的性能,包括通过禁用 Nagle 算法来减少传输延迟、通过设置缓冲区大小来提高带宽利用率,以及通过最小化系统调用次数来减少系统延迟。 调用负载,并使用可调内核参数来优化 Linux TCP/IP 堆栈。

优化时您还需要考虑应用程序的特征。 例如,您的应用程序是基于 LAN 还是通过 LAN 进行通信? 如果您的应用程序仅在 LAN 内运行,则增加缓冲区大小可能不会带来太大的改进,但启用巨型帧肯定会显着提高性能!

最后用 或 来检查优化后的结果。 在数据包级别看到的变化可以帮助证明使用这些技术进行的优化是否成功。

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报
Powered By DESTOON