【动手实验】发送接收窗口对 TCP传输性能的影响

环境准备

服务器信息

两台腾讯云机器 t04(172.19.0.4)、t11(172.19.0.11),系统为 Ubuntu 22.04,内核为 5.15.0-139-generic。默认 RT 在 0.16s 左右。

$ ping 172.19.0.4
PING 172.19.0.4 (172.19.0.4) 56(84) bytes of data.
64 bytes from 172.19.0.4: icmp_seq=1 ttl=64 time=0.195 ms
64 bytes from 172.19.0.4: icmp_seq=2 ttl=64 time=0.216 ms
64 bytes from 172.19.0.4: icmp_seq=3 ttl=64 time=0.253 ms
64 bytes from 172.19.0.4: icmp_seq=4 ttl=64 time=0.158 ms
64 bytes from 172.19.0.4: icmp_seq=5 ttl=64 time=0.164 ms
64 bytes from 172.19.0.4: icmp_seq=6 ttl=64 time=0.139 ms
64 bytes from 172.19.0.4: icmp_seq=7 ttl=64 time=0.134 ms
64 bytes from 172.19.0.4: icmp_seq=8 ttl=64 time=0.153 ms
64 bytes from 172.19.0.4: icmp_seq=9 ttl=64 time=0.157 ms
64 bytes from 172.19.0.4: icmp_seq=10 ttl=64 time=0.149 ms
64 bytes from 172.19.0.4: icmp_seq=11 ttl=64 time=0.148 ms
64 bytes from 172.19.0.4: icmp_seq=12 ttl=64 time=0.157 ms
64 bytes from 172.19.0.4: icmp_seq=13 ttl=64 time=0.151 ms
64 bytes from 172.19.0.4: icmp_seq=14 ttl=64 time=0.156 ms
64 bytes from 172.19.0.4: icmp_seq=15 ttl=64 time=0.156 ms
64 bytes from 172.19.0.4: icmp_seq=16 ttl=64 time=0.160 ms
64 bytes from 172.19.0.4: icmp_seq=17 ttl=64 time=0.159 ms
^C
--- 172.19.0.4 ping statistics ---
17 packets transmitted, 17 received, 0% packet loss, time 16382ms
rtt min/avg/max/mdev = 0.134/0.165/0.253/0.028 ms

内核参数信息

内核默认参数值

$ sudo sysctl -a | egrep "rmem|wmem|tcp_mem|adv_win|moderate"
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992
net.ipv4.tcp_adv_win_scale = 1
net.ipv4.tcp_mem = 41295	55062	82590
net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_rmem = 4096	131072	6291456
net.ipv4.tcp_wmem = 4096	16384	4194304
net.ipv4.udp_rmem_min = 4096
net.ipv4.udp_wmem_min = 4096
vm.lowmem_reserve_ratio = 256	256	32	0	0

参数含义如下:

  • 核心网络参数 (net.core.)
参数名称作用范围默认行为约束关系配置值影响
net.core.rmem_default所有协议套接字未设置SO_RCVBUF时的默认接收缓冲区UDP默认值,TCP有专门设置时被覆盖212992 (208KB)UDP接收缓冲区默认208KB
net.core.rmem_max所有协议套接字接收缓冲区的硬性上限覆盖所有协议的max设置212992 (208KB)严重限制:TCP最大6MB被压缩到208KB
net.core.wmem_default所有协议套接字未设置SO_SNDBUF时的默认发送缓冲区UDP默认值,TCP有专门设置时被覆盖212992 (208KB)UDP发送缓冲区默认208KB
net.core.wmem_max所有协议套接字发送缓冲区的硬性上限覆盖所有协议的max设置212992 (208KB)严重限制:TCP最大4MB被压缩到208KB
  • TCP专用参数 (net.ipv4.tcp_)
参数名称作用范围格式说明约束关系配置值实际效果
net.ipv4.tcp_rmem仅TCP连接[最小值 默认值 最大值]net.core.rmem_max硬性限制4096 131072 6291456最小4KB,默认128KB,最大被限制到208KB
net.ipv4.tcp_wmem仅TCP连接[最小值 默认值 最大值]net.core.wmem_max硬性限制4096 16384 4194304最小4KB,默认16KB,最大被限制到208KB
net.ipv4.tcp_mem全局TCP内存池[低水位 压力位 高水位] (页)独立于单连接缓冲区设置41295 55062 82590全局限制161MB-215MB-323MB
net.ipv4.tcp_moderate_rcvbufTCP动态调整0=关闭,1=开启在tcp_rmem范围内动态调整1开启动态调整,但被208KB限制
net.ipv4.tcp_adv_win_scaleTCP窗口计算整数值影响TCP窗口大小算法1适中的窗口缩放因子
  • UDP专用参数 (net.ipv4.udp_)
参数名称作用范围含义约束关系配置值实际效果
net.ipv4.udp_rmem_min仅UDP连接UDP接收缓冲区最小值net.core.rmem_max限制4096UDP最小接收缓冲区4KB
net.ipv4.udp_wmem_min仅UDP连接UDP发送缓冲区最小值net.core.wmem_max限制4096UDP最小发送缓冲区4KB
  • 内存管理参数 (vm.)
参数名称作用范围含义配置值影响
vm.lowmem_reserve_ratio系统内存管理各内存区域预留比例256 256 32 0 0防止内存区域被耗尽

上述参数结合 Socket 编程,对缓冲区的影响如下:

  • TCP Socket缓冲区行为
场景接收缓冲区 (SO_RCVBUF)发送缓冲区 (SO_SNDBUF)
不调用setsockopt()默认:131072 (128KB)默认:16384 (16KB)
调用setsockopt(1MB)实际:~425984 (208KB×2)实际:~425984 (208KB×2)
调用setsockopt(100KB)实际:~200KB (100KB×2)实际:~200KB (100KB×2)
动态调整范围4KB - 208KB (被限制)4KB - 208KB (被限制)
  • UDP Socket缓冲区行为
场景接收缓冲区 (SO_RCVBUF)发送缓冲区 (SO_SNDBUF)
不调用setsockopt()默认:212992 (208KB)默认:212992 (208KB)
调用setsockopt(1MB)实际:~425984 (208KB×2)实际:~425984 (208KB×2)
最小值保证不低于4KB不低于4KB
  • 参数间的优先级关系
1. net.core.*_max (硬性上限,覆盖一切)↓
2. net.ipv4.tcp_*mem (TCP专用设置)↓  
3. net.ipv4.udp_*mem (UDP专用设置)↓
4. net.core.*_default (通用默认值)↓
5. 应用程序setsockopt()调用

服务端启动

下面是生成测试文件和启动服务端的命令。

# 创建测试文件
# ubuntu @ t04 in ~/labs/01-bdp-tcp [10:32:12]
$ dd if=/dev/zero of=testfile  bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 8.3587 s, 257 MB/s# ubuntu @ t04 in ~/labs/01-bdp-tcp [10:32:30]
$ ll
total 2.1G
-rw-rw-r-- 1 ubuntu ubuntu 2.0G Jul 15 10:32 testfile# 启动服务端
# ubuntu @ t04 in ~/labs/01-bdp-tcp [10:32:50] C:1
$ python3 -m http.server 8089
Serving HTTP on 0.0.0.0 port 8089 (http://0.0.0.0:8089/) ...$ netstat -antp | grep 8089
tcp        0      0 0.0.0.0:8089            0.0.0.0:*               LISTEN      12808/python3

实验分析

环境准备好有,我们利用 tc 工具调整 rtt、丢包率以及调节发送接收缓冲大小,来看下不同情况下的数据传输效率。

1. 默认 mem ,默认延迟

首先不做任何改动,内网下载 2GB 的文件,耗时 14s,吞吐为 975Mbps。

2. 默认 mem,100ms 延迟

我们用 tc 将延迟增加到 100ms:

# 服务端机器添加 100ms 延迟
# ubuntu @ t04 in ~
$ sudo tc qdisc add dev eth0 root netem delay 100ms# 添加完成后客户端执行 ping 操作,延迟已经变成 100ms 了。
# ubuntu @ t11 in ~ [10:10:05]
$ ping 172.19.0.4
PING 172.19.0.4 (172.19.0.4) 56(84) bytes of data.
64 bytes from 172.19.0.4: icmp_seq=1 ttl=64 time=100 ms
64 bytes from 172.19.0.4: icmp_seq=2 ttl=64 time=100 ms

再次执行下载并抓包,结果如下:

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0  27.4M      0  0:01:14  0:01:14 --:--:-- 27.0M

可以看到整个下载耗时为 1 分 14s,吞吐为 229Mbps,和默认延迟相比,传输速度慢了不少,打开 tcptrace 查看传输过程,可以看到每 100ms 会暂停一次,因为服务端要等到 ack 后才会滑动窗口继续发送数据。

3. 默认 mem,默认延迟,1% 与 20% 丢包

服务端设置 1% 的丢包率

# ubuntu @ t04 in ~
sudo tc qdisc add dev eth0 root netem loss 1%

再次执行下载并抓包,结果如下:

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0   185M      0  0:00:11  0:00:11 --:--:--  255M


可以看到整体耗时 10s,平均吞吐为 185MBps。因为带宽足够并且 RT 非常小, 虽然引发了重传,但并没有导致拥塞窗口的减少,整体的传输速度没有受到明显的影响。

我们将丢包率调大到 20% 再次执行下载并抓包

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed0 2048M    0 15.0M    0     0   579k      0  1:00:20  0:00:26  0:59:54  410k

这次下载耗时预计达到了 1 个小时,传输过程查看 cwnd 可以看到已经缩小到了 1。

$ while true; do sudo ss -ti sport =  :8089 ; sleep 1; done;
State        Recv-Q        Send-Q                Local Address:Port                 Peer Address:Port         Process
ESTAB        0             33792                    172.19.0.4:8089                  172.19.0.11:46002cubic wscale:7,7 rto:204 rtt:0.325/0.358 ato:40 mss:8448 pmtu:8500 rcvmss:536 advmss:8448 cwnd:1 ssthresh:2 bytes_sent:47062993 bytes_retrans:9648128 bytes_acked:37397969 bytes_received:87 segs_out:5623 segs_in:3496 data_segs_out:5622 data_segs_in:1 send 208Mbps lastsnd:172 lastrcv:91576 lastack:172 pacing_rate 499Mbps delivery_rate 520Mbps delivered:4472 busy:91572ms sndbuf_limited:9616ms(10.5%) unacked:2 retrans:1/1150 lost:1 sacked:1 rcv_space:57076 rcv_ssthresh:57076 notsent:16896 minrtt:0.067
State        Recv-Q        Send-Q                Local Address:Port                 Peer Address:Port         Process
ESTAB        0             59136                    172.19.0.4:8089                  172.19.0.11:46002cubic wscale:7,7 rto:408 backoff:1 rtt:0.648/1.036 ato:40 mss:8448 pmtu:8500 rcvmss:536 advmss:8448 cwnd:1 ssthresh:2 bytes_sent:47919057 bytes_retrans:9800192 bytes_acked:38093521 bytes_received:87 segs_out:5725 segs_in:3559 data_segs_out:5724 data_segs_in:1 send 104Mbps lastsnd:48 lastrcv:92592 lastack:260 pacing_rate 375Mbps delivery_rate 814Mbps delivered:4556 busy:92588ms sndbuf_limited:9828ms(10.6%) unacked:3 retrans:1/1168 lost:1 sacked:2 rcv_space:57076 rcv_ssthresh:57076 notsent:33792 minrtt:0.067
State        Recv-Q        Send-Q                Local Address:Port                 Peer Address:Port         Process
ESTAB        0             8448                     172.19.0.4:8089                  172.19.0.11:46002cubic wscale:7,7 rto:204 rtt:0.41/0.467 ato:40 mss:8448 pmtu:8500 rcvmss:536 advmss:8448 cwnd:2 ssthresh:2 bytes_sent:48088017 bytes_retrans:9850880 bytes_acked:38228689 bytes_received:87 segs_out:5745 segs_in:3571 data_segs_out:5744 data_segs_in:1 send 330Mbps lastsnd:16 lastrcv:93604 lastack:16 pacing_rate 395Mbps delivery_rate 845Mbps delivered:4570 busy:93600ms sndbuf_limited:9828ms(10.5%) unacked:1 retrans:0/1174 rcv_space:57076 rcv_ssthresh:57076 minrtt:0.067
State        Recv-Q        Send-Q                Local Address:Port                 Peer Address:Port         Process
ESTAB        0             25344                    172.19.0.4:8089                  172.19.0.11:46002cubic wscale:7,7 rto:204 rtt:0.219/0.218 ato:40 mss:8448 pmtu:8500 rcvmss:536 advmss:8448 cwnd:1 ssthresh:2 bytes_sent:48483281 bytes_retrans:9926912 bytes_acked:38531025 bytes_received:87 segs_out:5792 segs_in:3601 data_segs_out:5791 data_segs_in:1 send 309Mbps lastsnd:184 lastrcv:94616 lastack:184 pacing_rate 1.11Gbps delivery_rate 583Mbps delivered:4608 busy:94612ms sndbuf_limited:9828ms(10.4%) unacked:3 retrans:1/1183 lost:1 sacked:2 rcv_space:57076 rcv_ssthresh:57076 minrtt:0.067

分析抓包文件,可以看到吞吐会周期性断崖式下跌然后在缓慢爬升。

在丢包时,接收端收到的包会乱序,会影响其 ACK 响应的速度,导致某些包在缓冲区中多等待一会,因此接收窗口也会间歇性的下降,并在收到重传包后恢复。

4. 默认 mem 和延迟,BBR 算法,20% 丢包

服务器默认使用的是 cubic 算法,受丢包影响较大,我们将算法改为 bbr 算法在测试下传输性能。

首先启用 BBR 拥塞控制算法:

$ sudo modprobe tcp_bbr
$ sudo sysctl -w net.ipv4.tcp_congestion_control=bbr

BBR 算法推荐结合 fq 调度算法使用,实验环境默认的是 fq_codel,我们利用 tc 来设置 fq 以及 20% 的丢包率,命令如下:

$ sudo tc qdisc add dev eth0 root handle 1: netem loss 20%# ubuntu @ t04 in ~/labs/01-bdp-tcp [12:09:13]
$ sudo tc qdisc add dev eth0 parent 1: handle 2: fq

完成后再次执行下载并抓包,结果如下:

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0  84.1M      0  0:00:24  0:00:24 --:--:--  140M

我们直接利用 tc 将拥塞控制算法设置为 bbr 并设置 20

  1. 默认 mem,默认延迟,bbr 算法,20% 丢包
$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0  84.1M      0  0:00:24  0:00:24 --:--:--  140M$ sudo tc qdisc add dev eth0 root handle 1: netem loss 20%# ubuntu @ t04 in ~/labs/01-bdp-tcp [12:09:13]
$ sudo tc qdisc add dev eth0 parent 1: handle 2: fq# ubuntu @ t04 in ~/labs/01-bdp-tcp [12:09:20]
$ sudo tc qdisc show dev eth0
qdisc netem 1: root refcnt 3 limit 1000 loss 20%
qdisc fq 2: parent 1: limit 10000p flow_limit 100p buckets 1024 orphan_mask 1023 quantum 17028b initial_quantum 85140b low_rate_threshold 550Kbit refill_delay 40ms timer_slack 10us horizon 10s horizon_drop
5. 客户端 recvbuf 为 4Kb,默认延迟

我们将客户端的 recvbuf 设置为 4Kb。

$ sudo sysctl -w "net.ipv4.tcp_rmem=4096        4096      4096"

在默认延迟下执行下载,抓包如下:

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0  14.8M      0  0:02:18  0:02:18 --:--:-- 14.8M

总体耗时两分多钟,抓包可以看到有大量 Window Full 的情况,但内网 RT 非常小,因此空出来后可以很快的通知给服务端,对整体传输速率的性能不算太大。

查看传输过程,可以看到大约每 40ms 接收窗口会上升,Linux 内核有一个宏定义来设置延迟确认的最小时间为 40ms,推测应该是 delayed ack 起了作用。

# https://elixir.bootlin.com/linux/v5.15.130/source/include/net/tcp.h#L135
# define TCP_DELACK_MIN	((unsigned)(HZ/25))	/* minimal time to delay before sending an ACK */
6. 客户端 recvbuf 为 4Kb,100ms 延迟

将延迟增加到 100ms 后,整体传输时间预计需要 29 小时,这种情况下,数据只能一点点发,而且耗时还比较长,整体传输速度变得巨慢无比。

$ sudo tc qdisc add dev eth0 root netem delay 100ms$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed0 2048M    0 2789k    0     0  20419      0 29:12:50  0:02:19 29:10:31 20451
7. 服务端 sendbuf 为 4Kb,默认延迟

下载时间只需要 10 几秒,对性能没有明显影响。虽然发送 buffer 小,但因为 rtt 也很小,ACK 包能很快回来可以立即释放 wmem,因此对速度影响不大。好比即使我们只有两辆货车,但装货发货非常快,货车卸完货能立马回来继续拉,整体运货速度也是有保证的,但如果卸货贼慢或者货车路上跑的贼慢,整体发货效率也提不上去。

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100 2048M  100 2048M    0     0   164M      0  0:00:12  0:00:12 --:--:--  195M

这里可以和实验 5 做对比,在默认延迟下修改 recvbuf 和 sendbuf,可以看到修改 recvbuf 对性能的影响更加明显。都是 RT 很小,但 server 端收到 ACK 后 sendbuf 清理出空间,可以立即发送,是内存级别的演示;但接收端在有 recvbuf 有空间后返回 ACK 到服务端,是网络通信级别的延迟,两者相差几个数量级。

图片来自 ## TCP性能和发送接收窗口、Buffer的关系

8. 服务端 sendbuf 为 4Kb,100ms 延迟

将延迟增大到 100ms 后,下载时间预计需要 1 小时 37 分钟,整体效率下降了很多。

$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed0 2048M    0 17.4M    0     0   357k      0  1:37:50  0:00:49  1:37:01  366k

抓包查看传输过程,可以看到整体传输过程是非常丝滑的,放大后看每 100ms 窗口才会增大,性能就是受 RT 的影响一直上不去。

性能问题复现

这里我们模拟任总遇到的场景,假设我们的带宽是 500Mbps,RT 为 10ms,通过调整发送 buffer 来优化发送效率。

BDP(Bandwidth-Delay Product) 带宽时延积

首先要理解一个概念带宽时延积:

Bandwidth-delay product (BDP)

Product of data link’s capacity and its end-to-end delay. The result is the maximum amount of unacknowledged data that can be in flight at any point in time.

《High Performance Browser Networking》

图片来自 High Performance Browser Networking

其含义就是整个传输链路上可以传输的最大数据,TCP 性能优化的一个关键点就是发送的数据要填满 BDP,从而充分利用带宽。就好比我们用货车拉货时,要尽可能将货车装满才能最大化其运力。

回我们 500Mbps 带宽,10ms RT 的场景,我们先来计算下 BDP 是 625KB,这意味着我们能够一下子发出 625KB 时才能最大化的利用网络带宽,对应到发送端的优化,则是将发送窗口大小设置为 BDP。

500Mbit/s * 0.01s = 5Mbits
# 转为 byte
5 * 10^6 bits / 8 = 625,000 bytes
# 转为 KB
625,000 bytes / 1000 = 625KB

在其他条件都满足的情况下,传输一个 512MB 大小的文件,理想传输速度大约为 8~10s 左右。下面是调整 sendbuf 后所得到的下载 512MB 大小文件的速度:

下面是调整 sendbuf 后所得到的下载 512MB 大小文件的速度:

  • sendbuf 为 100KB,下载时长 56s.
$ curl 172.19.0.4:8089/testfile > testfile% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100  512M  100  512M    0     0  9350k      0  0:00:56  0:00:56 --:--:-- 9363k
  • sendbuf 为 200KB,下载时长 24s。
$ curl 172.19.0.4:8089/testfile > /dev/null% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100  512M  100  512M    0     0  21.0M      0  0:00:24  0:00:24 --:--:-- 21.0M
  • sendbuf 为 700KB 或者 100KB,下载速度均为 8 ~ 9s。
$ curl 172.19.0.4:8089/testfile > /dev/null% Total    % Received % Xferd  Average Speed   Time    Time     Time  CurrentDload  Upload   Total   Spent    Left  Speed
100  512M  100  512M    0     0  58.4M      0  0:00:08  0:00:08 --:--:-- 58.7M

简要总结

整体来看,要想 TCP 数据传输的快,需要满足三个条件:

  • 发得快:发送端窗口足够,能填满 BDP,数据发送快。
  • 传得快:网络环境好,带宽大、RT 小、丢包率低。
  • 收的快:接收端数据处理快,接收窗口大。

在实际工作场景中,需要结合具体场景探查性能问题出现在哪一点,然后在寻找针对性的优化方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/89580.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/89580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

28、鸿蒙Harmony Next开发:不依赖UI组件的全局气泡提示 (openPopup)和不依赖UI组件的全局菜单 (openMenu)、Toast

目录 不依赖UI组件的全局气泡提示 (openPopup) 弹出气泡 创建ComponentContent 绑定组件信息 设置弹出气泡样式 更新气泡样式 关闭气泡 在HAR包中使用全局气泡提示 不依赖UI组件的全局菜单 (openMenu) 弹出菜单 创建ComponentContent 绑定组件信息 设置弹出菜单样…

让老旧医疗设备“听懂”新语言:CAN转EtherCAT的医疗行业应用

在医疗影像设备的智能化升级中,通信协议的兼容性常成为工程师的“痛点”。例如,某医院的移动式X射线机采用CAN协议控制机械臂,而主控系统基于EtherCAT架构。两者协议差异导致数据延迟高达5ms,影像定位精度下降,甚至影响…

ubuntu基础搭建

ubuntu上docker的搭建 https://vulhub.org/zh 网站最下面找到开始使用,有搭建的命令//安装docker,连接失败多试几次 curl -fsSL https://get.docker.com | sh //验证Docker是否正确安装: docker version //还要验证Docker Compose是否可用&am…

动态规划 + DFS + 记忆化!Swift 解 LeetCode 329 的实战笔记

文章目录摘要描述题解答案题解代码分析代码解析示例测试及结果时间复杂度空间复杂度总结摘要 这篇文章带你用 Swift 实战一道非常经典的 DFS 记忆化搜索题目 —— LeetCode 329《矩阵中的最长递增路径》。看似一个简单的“走格子”游戏,实则考察了搜索顺序、剪枝策…

046_局部内部类与匿名内部类

一、局部内部类(Local Inner Class) 1.1 定义与基本概念 局部内部类是定义在方法、构造器或代码块内部的类,其作用域仅限于所在的局部范围(定义它的方法、构造器或代码块),超出该范围则无法访问。 它的核心…

Jenkins Pipeline 中使用 JsonSlurper 报错:cannot find current thread

Jenkins Pipeline 中使用 JsonSlurper 报错:cannot find current thread🌟 背景⚠ 问题重现🧠 原因解析:CPS 与非 CPS 安全方法冲突✅ 解决方案一:使用 NonCPS 注解(经典方案)✅ 解决方案二&…

Go 语言循环语句详解

Go 语言循环语句详解 在编程语言中,循环语句是实现重复执行某些代码块的关键元素。Go 语言作为现代编程语言之一,提供了多种循环结构来满足不同的编程需求。本文将详细讲解 Go 语言中的循环语句,包括 for、while 和 goto 语句,帮助…

day30——零基础学嵌入式之进程间通信1.0

一、进程间通信7种方式1.传统的进程间通信方式(1)管道①无名管道:②有名管道:(2)③信号(3)system Ⅴ 》系统Ⅴ 进程间通信方式 inner Process Comunication④共享内存 &#xff…

408考研逐题详解:2010年第33题——网络体系结构

2010年第33题 下列选项中,不属于网络体系结构所描述的内容是( ) A. 网络的层次 \qquad B. 每层使用的协议 \qquad C. 协议的内部实现细节 \qquad D. 每层必须完成的功能 解析 本题属于计算机网络基础知识的范畴,考查网络体系结构…

VR 远程系统的沉浸式协作体验​

在传统的远程协作中,团队成员往往通过二维的视频画面进行交流,这种方式虽然能实现基本的沟通,但缺乏真实感和互动性。而 VR 远程系统的出现,彻底改变了这一局面。戴上 VR 设备,员工们仿佛置身于同一个真实的办公室空间…

记录DataGrip 2025.1.3破解失败后,无法重启问题修复

记录DataGrip 2025.1.3破解失败后,无法重启问题修复安装过程复盘异常场景解决方式总结安装过程 在官网下载了最新版本2025.1.3。安装成功后,使用30天试用方式,打开datagrip。 复盘异常场景 网上搜索破解教程进行破解。找了一个需要现在ja…

私有服务器AI智能体搭建配置选择记录

在搭建私有服务器上的AI智能体时,需要从多个方面进行选择和规划,以确保系统性能、安全性、可扩展性等方面满足需求。1. 硬件选择 服务器配置: CPU:选择高性能多核CPU(如Intel Xeon或AMD EPYC系列)&#xff…

SDC Specical check setting的描述 - false path

在上一篇文中描述了SDC的基本语法,其中关于时序异常约束并没有进行详细的描述,但是在正常的设计中,一般这种异常的设置反而是需要特别关注的,主要包括:1. 虚假路径- false path不需要满足任何时序要求的路径&#xff1…

【Python练习】048. 编写一个函数,实现简单的命令行接口,接受用户输入并响应

048. 编写一个函数,实现简单的命令行接口,接受用户输入并响应 在 Python 中,可以通过 input() 函数创建一个简单的命令行接口,接受用户输入并根据输入内容进行响应。 示例代码 def simple_command_line_interface():"""实现一个简单的命令行接口,接受用…

软件工厂语境下的知识系统选型:兼顾合规性与集成深度

在过去几十年间,制造业从“工匠手作”迈向“工业流水线”,完成了生产效率的巨大飞跃。当软件开发也面临交付复杂性、合规要求与协作成本不断上升的现实,“软件工厂”的理念逐步兴起。 在这场“开发现代化”的转型中,知识管理被重新…

C语言-一维数组,二维数组

数组 数组的引入如果要在程序中保存一个人的年龄?如何保存? 答:创建一个基于int类型的变量,举例:int age 22如果要在程序中保存一个人的三门课的成绩?如何保存? 答:创建三个基于flo…

如何区别HTML和HTML5?

要区分 HTML&#xff08;通常指 HTML4 及更早版本&#xff09;和 HTML5&#xff0c;主要可以从以下关键方面进行比较&#xff1a;一、文档声明区别 <!-- HTML4 文档声明 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http:/…

Java实战:实时聊天应用开发(附GitHub链接)

一、前置技术项目介绍&#xff1a; 项目为局域网沟通软件&#xff0c;类似内网通&#xff0c;核心功能包括昵称输入、聊天界面展示在线人数&#xff08;实时更新&#xff09;、群聊&#xff0c;也可扩展私聊、登录注册、聊天记录存储等功能&#xff0c;结尾附GitHub链接。项目涉…

linux 的list_for_each_entry

linux的宏定义提高了代码的简洁性&#xff0c;但有时候的命名不够完美。比如list_for_each_entry&#xff0c;看名字只知道是遍历list&#xff0c;但一看里面的三个变量参数&#xff0c;有点懵逼。/*** list_for_each_entry - iterate over list of given type* pos: …

分布式面试点

目录 1.分布式理论 为什么CAP不可兼得呢? 2.CAP对应的模型和应用 3.Base理论 4,有哪些分布式锁的案例 5.分布式事务 6.Seata 分布式一致性算法 1. 准备阶段&#xff08;Prepare Phase&#xff09; 2. 接受阶段&#xff08;Accept Phase&#xff09; 3. 学习阶段&…