在执行小型写操作时,我一直在努力解决SMB/CIFS共享的性能问题。
首先,让我描述一下我当前的网络设置:
[global]
printcap name=cups
winbind enum groups=yes
include=/var/tmp/nginx/smb.netbios.aliases.conf
socket options=TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536
security=user
local master=no
realm=*
passdb backend=smbpasswd
printing=cups
max protocol=SMB3
winbind enum users=yes
load printers=yes
workgroup=WORKGROUP
我目前正在用用C++编写的以下程序(在GitHub 这里上)测试小型写性能:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(int argc, char* argv[])
{
ofstream outFile(argv[1]);
for(int i = 0; i < 1000000; i++)
{
outFile << "Line #" << i << endl;
}
outFile.flush();
outFile.close();
return 0;
}
Linux挂载配置:
//192.168.1.10/nas-main on /mnt/nas-main type cifs (rw,noexec,nodev)
Linux上的程序运行时(网络输出峰值为100 peaks):
$ time ./nas-write-test /mnt/nas-main/home/will/test.txt
real 0m0.965s
user 0m0.148s
sys 0m0.672s
PCAP快照显示将多行分块到单个TCP数据包中:
PowerShell测量的Windows上的程序运行时:
> Measure-Command {start-process .\nas-write-test.exe -argumentlist "Z:\home\will\test-win.txt" -wait}
Days : 0
Hours : 0
Minutes : 9
Seconds : 29
Milliseconds : 316
Ticks : 5693166949
TotalDays : 0.00658931359837963
TotalHours : 0.158143526361111
TotalMinutes : 9.48861158166667
TotalSeconds : 569.3166949
TotalMilliseconds : 569316.6949
Windows上显示每个SMB写入请求的单行的PCAP快照:
这个程序在Windows上大约需要10分钟(~2.3Mbps)。显然,Windows显示了一个非常嘈杂的SMB会话,其有效负载效率非常低。
Windows上是否有任何可以提高小写入性能的设置?从数据包捕获的角度来看,Windows似乎没有正确地缓冲写入,而是一次一行地发送数据。然而,在Linux上,数据是大量缓冲的,因此性能要好得多。让我知道PCAP文件是否会有帮助,我可以找到一种方法来上传它们。
正如@sehafoc所提到的,我将servers max protocol
设置简化为SMB1,如下所示:
max protocol=NT1
上述设置导致了完全相同的行为。
我还通过在另一台Windows 10机器上创建一个共享来删除Samba变量,它还显示了与Samba服务器相同的行为,因此我开始相信这是Windows客户端的写缓存错误。
我还设置了一个NFS共享,Windows也没有为此提供缓冲。因此,据我所知,这绝对是Windows客户端的一个潜在问题,这是非常不幸的:-/
任何帮助都将不胜感激!
发布于 2016-10-13 03:28:18
使用SMB协议的远程文件操作(如读/写)的性能可能受到服务器和客户端分配的缓冲区大小的影响。缓冲区大小确定发送固定数据量所需的往返次数。每次在客户端和服务器之间发送请求和响应时,所花费的时间至少等于双方之间的延迟,这在广域网(WAN)中可能非常重要。
SMB缓冲区--可以通过以下注册表设置配置MaxBufferSize:
HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\SizeReqBuf
数据类型:REG_DWORD
范围: 1024到65535 (根据您的要求选择5000以上的值)
但是SMB签名会影响允许的最大缓冲区大小。因此,我们需要禁用SMB的签名,以及确定我们的目标。下面的注册表需要同时在服务器端创建,如果可能的话,也需要在客户端创建。
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManWorkstation\Parameters
值名称:EnableSecuritySignature
数据类型:REG_DWORD
数据:0(禁用),1(启用)
发布于 2016-10-13 21:12:19
我没有足够的声誉留下评论(我认为考虑到这个答案的验证程度,这样做会更好)。
我注意到,在Linux与Windows级别跟踪中有一个很大的差异,就是在Linux上使用SMB1,在Windows中使用SMB2。在SMB1 samba中,批处理oplock机制可能比SMB2独占租约实现执行得更好。在这两种情况下,都应该允许一定数量的客户端缓存。
( 1)可能尝试在Samba中设置一个较低的最大协议级别,以尝试使用SMB1 2)验证是否取消了独占的oplocks或租约
希望这会有所帮助:)
发布于 2017-10-09 15:27:24
有趣的现象。这是我要尝试的-我不知道这是否真的有帮助。如果是我的机器,我会广泛地观察SMB的计数器。其中一人会说出原因。
更多值得尝试的事情
如果SMB_RDR每行增加一个写I/O请求(这里不应该发生的事情),它可能有助于向执行引擎添加一些线程。
将"AdditionalCriticalWorkerThreads“设置为2,然后设置为4。
HKLM\System\CurrentControlSet\Control\Session Manager\Executive\AdditionalCriticalWorkerThreads
默认值为0,这意味着没有添加额外的关键内核工作线程。这通常是可以的。此值影响文件系统缓存用于预读和写后请求的线程数。提高这个值可以在存储子系统中允许更多排队的I/O (这很好,当您想逐行写入时),但是CPU更昂贵。
增加"AdditionalCriticalWorkerThreads“值会增加文件服务器用于服务并发请求的线程数。
HKLM\System\CurrentControlSet\Services\LanmanServer\Parameters\MaxThreadsPerQueue
缺省值为20。如果SMB2工作队列增长非常大,则指示可能需要增加该值(执行计数器“服务器工作队列\队列长度\SMB2 2*”)。应该是<100)。
https://serverfault.com/questions/808633
复制相似问题