Ghi nhỏ vào chia sẻ mạng SMB chậm trên Windows, nhanh qua CIFS Linux mount


10

Tôi đã phải vật lộn để khắc phục vấn đề về hiệu năng với chia sẻ SMB / CIFS khi thực hiện ghi nhỏ.

Trước tiên, hãy để tôi mô tả thiết lập mạng hiện tại của mình:

Người phục vụ

  • Synology DS215j (đã bật hỗ trợ SMB3)

Khách hàng (cùng máy tính có dây khởi động kép Gig-E)

  • Ubuntu 14.04.5 LTS, Tahr Trusty
  • Windows 8.1

smb.conf

[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

Tôi hiện đang thử nghiệm hiệu suất ghi nhỏ với chương trình sau được viết bằng C ++ (trên GitHub tại đây ):

#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;
}

Cấu hình gắn kết Linux:

//192.168.1.10/nas-main on /mnt/nas-main type cifs (rw,noexec,nodev)

Thời gian chạy chương trình trên Linux (đầu ra mạng cực đại ở mức ~ 100Mbps):

$ time ./nas-write-test /mnt/nas-main/home/will/test.txt

real    0m0.965s
user    0m0.148s
sys 0m0.672s

Ảnh chụp nhanh PCAP hiển thị phân đoạn nhiều dòng vào một gói TCP:

Ảnh chụp nhanh PCAP của Linux

Thời gian chạy chương trình trên Windows được đo bằng PowerShell:

> 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

Ảnh chụp nhanh PCAP trên Windows hiển thị một dòng trên mỗi Yêu cầu ghi SMB:

Ảnh chụp nhanh PCAP của Windows

Chương trình tương tự này mất khoảng 10 phút (~ 2.3Mbps) trên Windows. Rõ ràng, Windows PCAP cho thấy một cuộc trò chuyện SMB rất ồn ào với hiệu quả tải trọng rất thấp.

Có bất kỳ cài đặt nào trên Windows có thể cải thiện hiệu suất ghi nhỏ không? Có vẻ như khi nhìn vào các gói chụp, Windows không đệm ghi đúng cách và ngay lập tức gửi dữ liệu từng dòng một. Trong khi đó, trên Linux, dữ liệu được đệm rất nhiều và do đó có hiệu năng vượt trội hơn nhiều. Hãy cho tôi biết nếu các tệp PCAP sẽ hữu ích và tôi có thể tìm cách tải chúng lên.

Cập nhật 27/10/2016:

Như @sehafoc đã đề cập, tôi đã giảm max protocolcài đặt máy chủ Samba xuống SMB1 bằng cách sau:

max protocol=NT1

Các thiết lập ở trên dẫn đến hành vi chính xác tương tự.

Tôi cũng đã loại bỏ biến Samba bằng cách tạo chia sẻ trên một máy Windows 10 khác và nó cũng thể hiện hành vi tương tự như máy chủ Samba, vì vậy tôi bắt đầu tin rằng đây là lỗi ghi bộ đệm với các máy khách Windows nói chung.

Cập nhật: 10/06/17:

Chụp gói Linux đầy đủ (14MB)

Chụp gói Windows đầy đủ (375MB)

Cập nhật: 10/12/17:

Tôi cũng thiết lập một chia sẻ NFS và Windows cũng không có bộ đệm cho việc này. Vì vậy, đây chắc chắn là một vấn đề máy khách Windows tiềm ẩn theo như tôi có thể nói, điều này rất đáng tiếc: - /

Bất kỳ trợ giúp sẽ được đánh giá cao!

Câu trả lời:


2

Endl C ++ được xác định để xuất '\ n' theo sau là một lần xả. flush () là một hoạt động đắt tiền, do đó, bạn thường nên tránh sử dụng endl làm kết thúc mặc định của dòng vì nó có thể tạo ra chính xác vấn đề hiệu suất mà bạn đang gặp (và không chỉ với SMB, mà với bất kỳ dòng nào có dòng xả đắt tiền bao gồm cả quay cục bộ rỉ sét hoặc thậm chí là NVMe mới nhất với tỷ lệ đầu ra cao một cách lố bịch).

Thay thế endl bằng "\ n" sẽ khắc phục hiệu suất ở trên bằng cách cho phép hệ thống đệm như dự định. Ngoại trừ một số thư viện có thể tuôn ra "\ n", trong trường hợp đó bạn sẽ bị đau đầu nhiều hơn (xem /programming/21129162/tell-endl-not-to-flush để biết giải pháp ghi đè phương thức đồng bộ hóa () ).

Bây giờ để làm phức tạp mọi thứ, flush () chỉ được xác định cho những gì xảy ra trong bộ đệm thư viện. Tác động của việc xả nước lên hệ điều hành, đĩa và các bộ đệm ngoài khác không được xác định. Đối với Microsoft.NET "Khi bạn gọi phương thức FileStream.Flush, bộ đệm I / O của hệ điều hành cũng bị xóa." ( https://msdn.microsoft.com/en-us/l Library / 2wwhh1616 ( v = vs.110 ) .aspx ) Điều này làm cho việc tuôn ra đặc biệt tốn kém cho Visual Studio C ++ vì nó sẽ hoàn thành công việc viết lách phương tiện vật lý ở cuối máy chủ từ xa của bạn như bạn đang thấy. Mặt khác, GCC nói "Một lời nhắc nhở cuối cùng: thường có nhiều bộ đệm tham gia hơn là chỉ có ở cấp độ ngôn ngữ / thư viện. Bộ đệm hạt nhân, bộ đệm đĩa và những thứ tương tự cũng sẽ có hiệu lực. Kiểm tra và thay đổi chúng là phụ thuộc vào hệ thống . "https://gcc.gnu.org/onlinesocs/libstdc++/manual/streambufs.html ) Dấu vết Ubuntu của bạn dường như chỉ ra rằng bộ đệm hệ điều hành / mạng không bị xóa bởi thư viện tuôn ra (). Hành vi phụ thuộc hệ thống sẽ là lý do nhiều hơn để tránh endl và xả quá mức. Nếu bạn đang sử dụng VC ++, bạn có thể thử chuyển sang một công cụ phái sinh Windows GCC để xem các hành vi phụ thuộc hệ thống phản ứng như thế nào, hoặc sử dụng Wine để chạy Windows thực thi trên Ubuntu.

Nói chung, bạn cần phải suy nghĩ về các yêu cầu của bạn để xác định xem việc xả mọi dòng có phù hợp hay không. endl thường phù hợp với các luồng tương tác, chẳng hạn như màn hình (chúng tôi cần người dùng thực sự nhìn thấy đầu ra của chúng tôi và không theo cụm), nhưng nói chung không phù hợp với các loại luồng khác, bao gồm cả các tệp có thể đáng kể. Tôi đã thấy các ứng dụng tuôn ra trên mỗi lần ghi 1 và 2 và 4 và 8 byte ... thật không hay khi thấy HĐH nghiền hàng triệu IO để ghi tệp 1 MB.

Ví dụ, một tệp nhật ký có thể cần xóa mọi dòng nếu bạn đang gỡ lỗi một sự cố vì bạn cần phải xóa dòng trước khi xảy ra sự cố; trong khi một tệp nhật ký khác có thể không cần phải xóa mọi dòng nếu nó chỉ tạo ra ghi nhật ký thông tin dài dòng dự kiến ​​sẽ tự động xóa trước khi ứng dụng kết thúc. Nó không cần phải / hoặc như bạn có thể rút ra một lớp với thuật toán tuôn ra tinh vi hơn để phù hợp với các yêu cầu cụ thể.

So sánh trường hợp của bạn với trường hợp tương phản của những người cần đảm bảo dữ liệu của họ hoàn toàn được lưu vào đĩa và không dễ bị tổn thương trong bộ đệm hệ điều hành ( /programming/7522479/how-do-i-ensure-data -is-write-to-đĩa-before-clos-fux ).

Lưu ý rằng như đã viết, outFile.flush () là không cần thiết vì nó tuôn ra một dòng đã được tuôn ra. Để trở thành pedantic, bạn nên sử dụng endl một mình hoặc tốt nhất là "\ n" với outFile.flush () nhưng không phải cả hai.


Cảm ơn rất nhiều! Bạn xứng đáng nhận được hơn 100 điểm, nhưng đó là tất cả những gì tôi có thể cho :) Đây chắc chắn là vấn đề!
mevatron

2

Tôi không có đủ danh tiếng để để lại nhận xét (mà tôi nghĩ sẽ tốt hơn nếu đưa ra mức độ xác minh cho câu trả lời này).

Tôi nhận thấy rằng một sự khác biệt lớn trong theo dõi cấp độ Linux và Windows của bạn là bạn đang sử dụng SMB1 trên Linux và SMB2 trong Windows. Có lẽ cơ chế oplock hàng loạt thực hiện tốt hơn trong samba SMB1 so với triển khai cho thuê độc quyền SMB2. Trong cả hai trường hợp, những thứ này sẽ cho phép một số lượng bộ nhớ đệm phía máy khách.

1) Có lẽ thử đặt mức giao thức tối đa thấp hơn trong Samba để thử các cửa sổ với SMB1 2) Xác thực rằng các oplocks hoặc cho thuê độc quyền được lấy ra

Hi vọng điêu nay co ich :)


2

Hiệu năng của các hoạt động tệp từ xa, chẳng hạn như đọc / ghi, sử dụng giao thức SMB có thể bị ảnh hưởng bởi kích thước bộ đệm được phân bổ bởi máy chủ và máy khách. Kích thước bộ đệm xác định số lượng chuyến đi khứ hồi cần thiết để gửi một lượng dữ liệu cố định. Mỗi khi yêu cầu và phản hồi được gửi giữa máy khách và máy chủ, lượng thời gian thực hiện bằng ít nhất là độ trễ giữa hai bên, điều này có thể rất có ý nghĩa trong trường hợp Mạng diện rộng (WAN).

Bộ đệm SMB - MaxBufferSize có thể được cấu hình thông qua cài đặt đăng ký sau:

HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\SizeReqBuf

Loại dữ liệu: REG_DWORD

Phạm vi: 1024 đến 65535 (Chọn giá trị theo yêu cầu của bạn trên 5000)

NHƯNG ĐĂNG KÝ SMB ảnh hưởng đến kích thước bộ đệm tối đa được phép. Do đó, chúng tôi cần phải vô hiệu hóa việc ký SMB để xác định mục tiêu của chúng tôi. Theo dõi đăng ký cần phải được tạo ở cả phía máy chủ và nếu có thể ở phía máy khách.

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManWorkstation\Parameters

Tên giá trị: EnableSecuritySignature

Loại dữ liệu: REG_DWORD

Dữ liệu: 0 (tắt), 1 (bật)


Cảm ơn vì tiền hỗ trợ; tuy nhiên, tôi đã thử cả hai biện pháp này và tôi vẫn thấy hành vi trên: - /
mevatron

Bạn cũng muốn kiểm tra tại sao "Synology DS215j" không sử dụng SMB3. Theo mặc định SMB3 được bật trên Win 8.1.
Adi Jha

1

Hiện tượng thú vị. Đây là những gì tôi sẽ thử - Tôi không biết nếu điều này thực sự có ích. Nếu đó là máy của tôi, tôi sẽ theo dõi rộng rãi những người hoàn hảo của SMB. Một trong số họ sẽ chỉ ra nguyên nhân.

Nhiều thứ để thử

Thêm chủ đề công nhân

Trong trường hợp SMB_RDR thực hiện một Yêu cầu I / O ghi trên mỗi dòng (điều không nên xảy ra ở đây), có thể giúp thêm một số luồng vào công cụ thực thi.

Đặt "ExtraCriticalWorkerThreads" thành 2, sau đó thành 4.

HKLM\System\CurrentControlSet\Control\Session Manager\Executive\AdditionalCriticalWorkerThreads

Mặc định là 0, có nghĩa là không có luồng xử lý kernel quan trọng nào được thêm vào. Mà thường thì ok. Giá trị này ảnh hưởng đến số lượng luồng mà bộ đệm của hệ thống tệp sử dụng cho các yêu cầu đọc trước và ghi phía sau. Tăng giá trị này có thể cho phép nhiều I / O được xếp hàng hơn trong hệ thống con lưu trữ (điều này tốt, khi bạn muốn viết từng dòng một), nhưng nó tốn nhiều CPU hơn.

Thêm chiều dài hàng đợi

Việc tăng giá trị "ExtraCriticalWorkerThreads" sẽ tăng số lượng luồng mà máy chủ tệp có thể sử dụng để phục vụ các yêu cầu đồng thời .

HKLM\System\CurrentControlSet\Services\LanmanServer\Parameters\MaxThreadsPerQueue

Mặc định là 20. Một dấu hiệu cho thấy giá trị có thể cần phải tăng là nếu hàng đợi công việc SMB2 đang tăng rất lớn (hàng đợi làm việc của máy chủ nước hoa \ Hàng đợi dài \ SMB2 * '. <100).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.