Tôi tự hỏi tại sao NFS v4 sẽ nhanh hơn NFS v3 rất nhiều và nếu có bất kỳ tham số nào trên v3 có thể được điều chỉnh.
Tôi gắn kết một hệ thống tập tin
sudo mount -o 'rw,bg,hard,nointr,rsize=1048576,wsize=1048576,vers=4' toto:/test /test
và sau đó chạy
dd if=/test/file of=/dev/null bs=1024k
Tôi có thể đọc 200-400MB / s nhưng khi tôi thay đổi phiên bản thành vers=3
, phát lại và chạy lại dd tôi chỉ nhận được 90MB / s . Tệp tôi đang đọc là một tệp trong bộ nhớ trên máy chủ NFS. Cả hai mặt của kết nối là Solaris và có 10GbE NIC. Tôi tránh bất kỳ bộ nhớ đệm phía máy khách nào bằng cách nối lại giữa tất cả các bài kiểm tra. Tôi đã từng dtrace
thấy trên máy chủ để đo tốc độ dữ liệu được phục vụ thông qua NFS. Đối với cả v3 và v4 tôi đã thay đổi:
nfs4_bsize
nfs3_bsize
từ mặc định 32K đến 1M (trên v4 tôi đã đạt tối đa 150MB / giây với 32K) Tôi đã thử điều chỉnh
- nfs3_max_threads
- clnt_max_conns
- nfs3_async_cl cluster
để cải thiện hiệu suất v3, nhưng không đi.
Trên v3 nếu tôi chạy bốn song song dd
, thông lượng giảm từ 90MB / s xuống 70-80 MB khiến tôi tin rằng vấn đề là một số tài nguyên được chia sẻ và nếu vậy, tôi tự hỏi đó là gì và liệu tôi có thể tăng nó không nguồn.
mã dtrace để có được kích thước cửa sổ:
#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option defaultargs
inline string ADDR=$$1;
dtrace:::BEGIN
{
TITLE = 10;
title = 0;
printf("starting up ...\n");
self->start = 0;
}
tcp:::send, tcp:::receive
/ self->start == 0 /
{
walltime[args[1]->cs_cid]= timestamp;
self->start = 1;
}
tcp:::send, tcp:::receive
/ title == 0 &&
( ADDR == NULL || args[3]->tcps_raddr == ADDR ) /
{
printf("%4s %15s %6s %6s %6s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s\n",
"cid",
"ip",
"usend" ,
"urecd" ,
"delta" ,
"send" ,
"recd" ,
"ssz" ,
"sscal" ,
"rsz",
"rscal",
"congw",
"conthr",
"flags",
"retran"
);
title = TITLE ;
}
tcp:::send
/ ( ADDR == NULL || args[3]->tcps_raddr == ADDR ) /
{
nfs[args[1]->cs_cid]=1; /* this is an NFS thread */
this->delta= timestamp-walltime[args[1]->cs_cid];
walltime[args[1]->cs_cid]=timestamp;
this->flags="";
this->flags= strjoin((( args[4]->tcp_flags & TH_FIN ) ? "FIN|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_SYN ) ? "SYN|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_RST ) ? "RST|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_PUSH ) ? "PUSH|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_ACK ) ? "ACK|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_URG ) ? "URG|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_ECE ) ? "ECE|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_CWR ) ? "CWR|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags == 0 ) ? "null " : ""),this->flags);
printf("%5d %14s %6d %6d %6d %8d \ %-8s %8d %6d %8d %8d %8d %12d %s %d \n",
args[1]->cs_cid%1000,
args[3]->tcps_raddr ,
args[3]->tcps_snxt - args[3]->tcps_suna ,
args[3]->tcps_rnxt - args[3]->tcps_rack,
this->delta/1000,
args[2]->ip_plength - args[4]->tcp_offset,
"",
args[3]->tcps_swnd,
args[3]->tcps_snd_ws,
args[3]->tcps_rwnd,
args[3]->tcps_rcv_ws,
args[3]->tcps_cwnd,
args[3]->tcps_cwnd_ssthresh,
this->flags,
args[3]->tcps_retransmit
);
this->flags=0;
title--;
this->delta=0;
}
tcp:::receive
/ nfs[args[1]->cs_cid] && ( ADDR == NULL || args[3]->tcps_raddr == ADDR ) /
{
this->delta= timestamp-walltime[args[1]->cs_cid];
walltime[args[1]->cs_cid]=timestamp;
this->flags="";
this->flags= strjoin((( args[4]->tcp_flags & TH_FIN ) ? "FIN|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_SYN ) ? "SYN|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_RST ) ? "RST|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_PUSH ) ? "PUSH|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_ACK ) ? "ACK|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_URG ) ? "URG|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_ECE ) ? "ECE|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags & TH_CWR ) ? "CWR|" : ""),this->flags);
this->flags= strjoin((( args[4]->tcp_flags == 0 ) ? "null " : ""),this->flags);
printf("%5d %14s %6d %6d %6d %8s / %-8d %8d %6d %8d %8d %8d %12d %s %d \n",
args[1]->cs_cid%1000,
args[3]->tcps_raddr ,
args[3]->tcps_snxt - args[3]->tcps_suna ,
args[3]->tcps_rnxt - args[3]->tcps_rack,
this->delta/1000,
"",
args[2]->ip_plength - args[4]->tcp_offset,
args[3]->tcps_swnd,
args[3]->tcps_snd_ws,
args[3]->tcps_rwnd,
args[3]->tcps_rcv_ws,
args[3]->tcps_cwnd,
args[3]->tcps_cwnd_ssthresh,
this->flags,
args[3]->tcps_retransmit
);
this->flags=0;
title--;
this->delta=0;
}
Đầu ra trông giống như (không phải từ tình huống cụ thể này):
cid ip usend urecd delta send recd ssz sscal rsz rscal congw conthr flags retran
320 192.168.100.186 240 0 272 240 \ 49232 0 1049800 5 1049800 2896 ACK|PUSH| 0
320 192.168.100.186 240 0 196 / 68 49232 0 1049800 5 1049800 2896 ACK|PUSH| 0
320 192.168.100.186 0 0 27445 0 \ 49232 0 1049800 5 1049800 2896 ACK| 0
24 192.168.100.177 0 0 255562 / 52 64060 0 64240 0 91980 2920 ACK|PUSH| 0
24 192.168.100.177 52 0 301 52 \ 64060 0 64240 0 91980 2920 ACK|PUSH| 0
một số tiêu đề
usend - unacknowledged send bytes
urecd - unacknowledged received bytes
ssz - send window
rsz - receive window
congw - congestion window
lập kế hoạch lấy snoop của dd trên v3 và v4 và so sánh. Đã thực hiện nó nhưng có quá nhiều lưu lượng truy cập và tôi đã sử dụng một tệp đĩa thay vì một tệp được lưu trong bộ nhớ cache khiến việc so sánh thời gian trở nên vô nghĩa. Sẽ chạy các snoop khác với dữ liệu được lưu trong bộ nhớ cache và không có lưu lượng khác giữa các hộp. TBD
Ngoài ra, các nhà mạng nói rằng không có định hình lưu lượng hoặc giới hạn băng thông trên các kết nối.