Tại sao dd sử dụng ghi trực tiếp vào đĩa chậm hơn là vào tệp


7

Tôi đang cố gắng so sánh tốc độ ghi tổng hợp khi ghi vào tệp trong hệ thống tệp GPFS, so với ghi trực tiếp vào đĩa trên hệ thống với Red Hat Enterprise Linux Server phát hành 6.4 (Santiago). Đối với ứng dụng của tôi, tôi cần đo tốc độ thô, tức là không tận dụng bộ đệm. Tôi không hiểu tác động của tùy chọn trực tiếp được sử dụng ddđể bỏ qua bộ đệm. Khi ghi trực tiếp vào thiết bị khối, tôi nhận được tỷ lệ thấp hơn đáng kể khi tôi sử dụng oflag=direct, so với ghi vào tệp trong hệ thống tệp GPFS. Lý do tại sao điều này xảy ra?

Để đo tốc độ tổng hợp, tôi tạo pcác quy trình đang chạy ddđồng thời ghi vào thiết bị khối hoặc tệp. Sau đó tôi tổng các ptỷ lệ thu được để có được tỷ lệ ghi tổng hợp.

    #!/bin/bash
    directdiskrate=~/scratch/rate5
    syncdiskrate=~/scratch/rate4
    filerate=~/scratch/rate3
    numruns=1
    numthreads=30

    #to disk use both conv=fsync and oflag=direct
    writetodiskdirect="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync oflag=direct iflag=fullblock"
    for p in $(seq $numthreads)
    do
             #parses output of dd, rate is on last line, each field separated by ,s
            $writetodiskdirect 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$directdiskrate&
    done
    wait

    #to disk use only conv=fsync option
    writetodisksync="dd if=/dev/zero of=/dev/sdac bs=256k count=4096 conv=fsync iflag=fullblock"
    for p in $(seq $numthreads)
    do
       #parses output of dd, rate is on last line, each field separated by ,s
       $writetodisksync 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$syncdiskrate&
    done
    wait

    #to file use both conv=fsync and oflag=direct
    for p in $(seq $numthreads)
    do
        writetofile="dd if=/dev/zero of=/gpfs1/fileset6/file$p bs=256k count=4096 conv=fsync oflag=direct"
        #parses output of dd, rate is on last line, each field separated by ,s
        $writetofile 2>&1|tail -n 1|awk 'BEGIN { FS = "," } ; { print $3 }'|sed -e 's/MB\/s//g'>>$filerate&
    done
    wait

Kết quả: Tốc độ ghi của mỗi 30 quy trình như sau:

  1. Ghi vào đĩa bằng conv=fsynctùy chọn, mỗi quá trình có tốc độ ghi ~ 180MB / s
  2. Ghi vào đĩa bằng cả hai conv=fsyncoflag=direct, mỗi quá trình có tốc độ ghi ~ 9MB / s
  3. Ghi vào một tệp trong hệ thống tệp GPFS, sử dụng cả hai conv=fsyncoflag=direct, có tốc độ ghi ~ 80MB / s

Bạn có quản lý để tìm một tổ hợp các cờ làm cho việc ghi vào một tệp (thông qua lớp hệ thống tệp) chậm hơn so với việc ghi trực tiếp vào thiết bị khối không? fsync dường như hoạt động trên một số loại hệ thống tập tin, nhưng khi sử dụng FUSE exfat, nó dường như vẫn còn lưu trữ.
austinmarton

Câu trả lời:


5

Sự khác biệt này chắc chắn có một điều: bộ nhớ đệm.

Sẽ rất khó để xác định vị trí, đặc biệt là từ vùng người dùng, nhưng tất cả các hệ thống tập tin bộ đệm (bộ đệm) của hạt nhân Linux đều ghi, trừ khi bạn thực hiện các thủ thuật để có được ghi đồng bộ. Đó là, kernel sẽ lưu dữ liệu ddgửi đến một tệp ở đâu đó trong bộ nhớ kernel. Kernel có thể sử dụng mã hệ thống tập tin để làm điều này. Một thời gian trong tương lai, kernel sẽ lên lịch cho một khối đĩa đi ra đĩa. Điều đó sẽ xảy ra "không đồng bộ", đôi khi sau khi kernel nói ddrằng việc ghi kết thúc.

Lý do cho điều này là việc di chuyển byte qua bus và vào ổ đĩa, sau đó chuyển sang đĩa platt chậm hơn nhiều so với việc sao chép từ người dùng sang bộ nhớ kernel. Thông thường, các chương trình không quan tâm quá nhiều đến việc dữ liệu họ vừa "ghi" sẽ không lưu vào đĩa trong một thời gian. Độ tin cậy phần cứng đủ cao để dữ liệu làm cho nó gần như luôn luôn.

Đó là câu trả lời đơn giản, nhưng một khi bạn đã đọc / ghi / xóa tất cả bộ đệm trong kernel, mã hệ thống tệp có thể tận dụng thời gian tồn tại của tệp ngắn bằng cách không bao giờ ghi dữ liệu của các tệp bị xóa trước khi chúng bị xóa đĩa. Mã hệ thống tệp có thể nhóm ghi để tận dụng các khối đĩa lớn hơn một nhóm ghi và hợp nhất chúng thành một lần ghi. Có hàng tấn tối ưu hóa có thể được thực hiện trong hầu hết các hệ thống tệp.


Điều này có nghĩa là mặc dù sử dụng tùy chọn oflag = direct với dd write to file, việc ghi vẫn đi qua bộ đệm? Nhưng oflag = direct thực sự có hiệu lực khi ghi trực tiếp vào thiết bị khối?
dùng3216949

@ user3216949 - Tôi nghĩ đó là sự thật, nhưng tôi không có kiến ​​thức trực tiếp. Thiết bị khối nằm ở cuối người dùng -> kernel -> hệ thống tệp -> các lớp ổ đĩa. Theo tôi hiểu, sử dụng thiết bị khối sẽ loại bỏ (các) lớp hệ thống tệp trong ngăn xếp.
Bruce Ediger

@Bruce có cách nào (như một công cụ) để xác minh rằng việc ghi có đi qua bộ đệm hay không?
felix

@ user3216949 Nếu bạn muốn đảm bảo dữ liệu thực sự được ghi ra đĩa, hãy sử dụng một trong : conv=fdatasync conv=fsync oflag=dsync oflag=sync.
Patrick

2

Bộ nhớ cache của các chương trình sao chép làm cho nó nhanh hơn sau đó sử dụng dd tôi sẽ giả sử.

Nếu đây là ứng dụng chuyên sâu đĩa duy nhất đang chạy, hãy đợi chương trình thoát ra rồi chạy:

$ sync; sync 

Điều này sẽ xóa bộ nhớ cache ngay lập tức. Nếu phải mất một lúc để quay lại dấu nhắc bạn biết nó đã nhấn bộ đệm.

Tôi làm điều này trước khi kéo các ổ đĩa USB của mình và thường mất khá nhiều thời gian từ khi sao chép xong đến bộ đệm vào đĩa.


Cảm ơn, tôi nhận ra bằng cách sử dụng đề xuất của bạn, rằng ngay cả khi sử dụng dữ liệu một mình fsync cuối cùng cũng được ghi vào đĩa, nhưng có lẽ hiệu quả hơn khi ghi một số lượng lớn.
dùng3216949

0

Câu trả lời cho điều này có thể phức tạp. O_DIRECTlà một gợi ý hơn là một đơn đặt hàng và các hệ thống tập tin được phép bỏ qua nó trên Linux và chỉ sử dụng bộ đệm bộ đệm. Theo " Cân nhắc về việc sử dụng I / O trực tiếp (O_DIRECT) cho các ứng dụng GPFS" GPFS có thể quay trở lại hoạt động được đệm (tiếp theo là O_SYNC) khi mọi thứ không hoàn hảo. Những điều sau đây có thể áp dụng trong kịch bản của người hỏi:

Việc ghi làm cho tập tin tăng kích thước.

Chúng tôi không thể biết nếu ddmở rộng (các) tệp. Nếu đó là I / O đã đi qua bộ đệm bộ đệm trong trường hợp hệ thống tập tin và KHÔNG trong trường hợp trực tiếp đến trường hợp thiết bị khối.

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.