đ: Làm thế nào để tính toán kích thước khối tối ưu? [đóng cửa]


122

Làm thế nào để bạn tính toán kích thước khối tối ưu khi chạy a dd? Tôi đã nghiên cứu nó một chút và tôi không tìm thấy bất kỳ điều gì cho thấy điều này sẽ được thực hiện như thế nào.

Tôi có ấn tượng rằng kích thước khối lớn hơn sẽ dẫn đến nhanh hơn dd... điều này có đúng không?

Tôi sắp có ddhai ổ cứng Hitachi 500gb giống hệt nhau chạy ở tốc độ 7200 vòng / phút trên một hộp chạy Intel Core i3 với RAM 4GB DDR3 1333mhz, vì vậy tôi đang cố gắng tìm ra kích thước khối nào để sử dụng. (Tôi sẽ khởi động Ubuntu 10.10 x86 từ ổ đĩa flash và chạy nó từ đó.)


Thông qua @ câu trả lời tdg5 cho MacOS - macos_dd_ibs_test.shmacos_dd_obs_test.sh
MIXEL

1
câu trả lời tốt nhất là đóng góp một tính năng để ddtìm kích thước khối tối ưu trong khi chuyển tệp
Boris

Tại sao điều này bị đánh dấu là lạc đề và không được chuyển sang superuser?
dùng267092

Câu trả lời:


95

Kích thước khối tối ưu phụ thuộc vào các yếu tố khác nhau, bao gồm hệ điều hành (và phiên bản của nó), các bus và đĩa cứng khác nhau liên quan. Một số hệ thống giống Unix (bao gồm cả Linux và ít nhất là một số hương vị của BSD) xác định st_blksizethành viên trong struct statđó cung cấp những gì hạt nhân cho là kích thước khối tối ưu:

#include <sys/stat.h>
#include <stdio.h>

int main(void)
{
    struct stat stats;

    if (!stat("/", &stats))
    {
        printf("%u\n", stats.st_blksize);
    }
}

Cách tốt nhất có thể là thử nghiệm: sao chép một gigabyte với các kích thước và thời gian khối khác nhau. (Hãy nhớ xóa bộ đệm của bộ đệm hạt nhân trước mỗi lần chạy echo 3 > /proc/sys/vm/drop_caches:).

Tuy nhiên, theo nguyên tắc chung, tôi thấy rằng kích thước khối đủ lớn ddsẽ thực hiện tốt công việc và sự khác biệt giữa 64 KiB và 1 MiB là nhỏ, so với 4 KiB so với 64 KiB. (Mặc dù, phải thừa nhận rằng, đã lâu rồi tôi chưa làm điều đó. Tôi sử dụng mebibyte theo mặc định, hoặc chỉ để ddchọn kích thước.)


11
Tôi rất xin lỗi vì đã không bao giờ chấp nhận đây là câu trả lời ... cảm ơn!
eckza

Điểm tuyệt vời về việc nhớ thả bộ nhớ cache. Điều này đã làm sai số đo của tôi! (Mặc dù vấn đề nhỏ: đó là "drop_caches", có dấu gạch dưới. Rõ ràng các chỉnh sửa cần có ít nhất 6 ký tự ... :()
Tom

73

Như những người khác đã nói, không có kích thước khối chính xác phổ biến; những gì là tối ưu cho một tình huống hoặc một phần cứng có thể kém hiệu quả đối với một phần cứng khác. Ngoài ra, tùy thuộc vào tình trạng của đĩa, có thể thích sử dụng kích thước khối khác với kích thước khối "tối ưu".

Một điều khá đáng tin cậy trên phần cứng hiện đại là kích thước khối mặc định là 512 byte có xu hướng gần như chậm hơn một thứ tự độ lớn so với một giải pháp thay thế tối ưu hơn. Khi nghi ngờ, tôi thấy rằng 64K là một mặc định hiện đại khá vững chắc. Mặc dù 64K thường không phải là kích thước khối tối ưu, theo kinh nghiệm của tôi, nó có xu hướng hiệu quả hơn nhiều so với mặc định. 64K cũng có một lịch sử khá vững chắc về hiệu suất đáng tin cậy: Bạn có thể tìm thấy một thông báo từ danh sách gửi thư Eug-Lug, khoảng năm 2002, đề xuất kích thước khối là 64K tại đây: http://www.mail-archive.com/eug- lug@efn.org/msg12073.html

Để xác định kích thước khối đầu ra tối ưu THE, tôi đã viết đoạn mã sau để kiểm tra việc viết tệp kiểm tra 128M với dd ở một loạt các kích thước khối khác nhau, từ mặc định là 512 byte đến tối đa là 64M. Hãy cảnh báo, tập lệnh này sử dụng dd nội bộ, vì vậy hãy sử dụng một cách thận trọng.

dd_obs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_obs_testfile}
TEST_FILE_EXISTS=0
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=1; fi
TEST_FILE_SIZE=134217728

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Calculate number of segments required to copy
  COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))

  if [ $COUNT -le 0 ]; then
    echo "Block size of $BLOCK_SIZE estimated to require $COUNT blocks, aborting further tests."
    break
  fi

  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Create a test file with the specified block size
  DD_RESULT=$(dd if=/dev/zero of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync 2>&1 1>/dev/null)

  # Extract the transfer rate from dd's STDERR output
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  # Clean up the test file if we created one
  if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

  # Output the result
  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

Xem trên GitHub

Tôi chỉ thử nghiệm tập lệnh này trên hệ thống Debian (Ubuntu) và trên OSX Yosemite, vì vậy có thể sẽ cần một số chỉnh sửa để hoạt động trên các phiên bản Unix khác.

Theo mặc định, lệnh sẽ tạo một tệp thử nghiệm có tên dd_obs_testfile trong thư mục hiện tại. Ngoài ra, bạn có thể cung cấp đường dẫn đến tệp thử nghiệm tùy chỉnh bằng cách cung cấp đường dẫn sau tên tập lệnh:

$ ./dd_obs_test.sh /path/to/disk/test_file

Đầu ra của tập lệnh là danh sách các kích thước khối được thử nghiệm và tốc độ truyền tải tương ứng của chúng như sau:

$ ./dd_obs_test.sh
block size : transfer rate
       512 : 11.3 MB/s
      1024 : 22.1 MB/s
      2048 : 42.3 MB/s
      4096 : 75.2 MB/s
      8192 : 90.7 MB/s
     16384 : 101 MB/s
     32768 : 104 MB/s
     65536 : 108 MB/s
    131072 : 113 MB/s
    262144 : 112 MB/s
    524288 : 133 MB/s
   1048576 : 125 MB/s
   2097152 : 113 MB/s
   4194304 : 106 MB/s
   8388608 : 107 MB/s
  16777216 : 110 MB/s
  33554432 : 119 MB/s
  67108864 : 134 MB/s

(Lưu ý: Đơn vị của tốc độ truyền sẽ thay đổi theo hệ điều hành)

Để kiểm tra kích thước khối đọc tối ưu, bạn có thể sử dụng nhiều hơn hoặc ít hơn cùng một quy trình, nhưng thay vì đọc từ / dev / zero và ghi vào đĩa, bạn sẽ đọc từ đĩa và ghi vào / dev / null. Một tập lệnh để thực hiện việc này có thể trông giống như sau:

dd_ibs_test.sh:

#!/bin/bash

# Since we're dealing with dd, abort if any errors occur
set -e

TEST_FILE=${1:-dd_ibs_testfile}
if [ -e "$TEST_FILE" ]; then TEST_FILE_EXISTS=$?; fi
TEST_FILE_SIZE=134217728

# Exit if file exists
if [ -e $TEST_FILE ]; then
  echo "Test file $TEST_FILE exists, aborting."
  exit 1
fi
TEST_FILE_EXISTS=1

if [ $EUID -ne 0 ]; then
  echo "NOTE: Kernel cache will not be cleared between tests without sudo. This will likely cause inaccurate results." 1>&2
fi

# Create test file
echo 'Generating test file...'
BLOCK_SIZE=65536
COUNT=$(($TEST_FILE_SIZE / $BLOCK_SIZE))
dd if=/dev/urandom of=$TEST_FILE bs=$BLOCK_SIZE count=$COUNT conv=fsync > /dev/null 2>&1

# Header
PRINTF_FORMAT="%8s : %s\n"
printf "$PRINTF_FORMAT" 'block size' 'transfer rate'

# Block sizes of 512b 1K 2K 4K 8K 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M 32M 64M
for BLOCK_SIZE in 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216 33554432 67108864
do
  # Clear kernel cache to ensure more accurate test
  [ $EUID -eq 0 ] && [ -e /proc/sys/vm/drop_caches ] && echo 3 > /proc/sys/vm/drop_caches

  # Read test file out to /dev/null with specified block size
  DD_RESULT=$(dd if=$TEST_FILE of=/dev/null bs=$BLOCK_SIZE 2>&1 1>/dev/null)

  # Extract transfer rate
  TRANSFER_RATE=$(echo $DD_RESULT | \grep --only-matching -E '[0-9.]+ ([MGk]?B|bytes)/s(ec)?')

  printf "$PRINTF_FORMAT" "$BLOCK_SIZE" "$TRANSFER_RATE"
done

# Clean up the test file if we created one
if [ $TEST_FILE_EXISTS -ne 0 ]; then rm $TEST_FILE; fi

Xem trên GitHub

Một sự khác biệt quan trọng trong trường hợp này là tệp thử nghiệm là tệp được viết bởi script. Không trỏ lệnh này vào tệp hiện có nếu không tệp hiện có sẽ bị ghi đè bằng các số 0!

Đối với phần cứng cụ thể của tôi, tôi thấy rằng 128K là kích thước khối đầu vào tối ưu nhất trên ổ cứng HDD và 32K là tối ưu nhất trên SSD.

Mặc dù câu trả lời này bao gồm hầu hết các phát hiện của tôi, nhưng tôi đã gặp phải trường hợp này đủ lần và tôi đã viết một bài đăng trên blog về nó: http://blog.tdg5.com/tuning-dd-block-size/ Bạn có thể tìm thêm chi tiết cụ thể trong các bài kiểm tra tôi đã thực hiện ở đó.


1
Tôi đã chạy tập lệnh thứ hai, kiểm tra hiệu suất đọc, trên rMBP 2015 với SSD 512G. Kích thước khối tốt nhất là 8388608: 3,582 GB byte / giây.
Quinn Comendant vào

1
CHỈNH SỬA: Tôi đã chạy tập lệnh thứ hai, kiểm tra hiệu suất đọc, trên rMBP 2015 với SSD 512GB. Kích thước khối tốt nhất là 524288 (5,754 GB / giây). Kích thước khối tốt thứ hai là 131072 (5,133 GB / giây). (Tôi sắp xếp các kết quả sai trong việc tạo ra giá trị cho lời nhận xét cuối cùng của tôi.)
Quinn Comendant

For dd_obs_test.sh conv=fsynckhông hoạt động trên macOS và có thể bị gỡ bỏ.
rynop

Theo kinh nghiệm của tôi, việc đo điểm chuẩn kích thước khối lớn hơn cần một mẫu lớn hơn để chính xác (vài giây. Tôi đoán tệp 128MB sẽ tạo ra nó nhưng tôi không chắc). Không chắc chắn lý do tại sao.
Rolf

2
Anh bạn! Thật là một câu trả lời đáng kinh ngạc. Nó giống như việc tìm ra một mỏ vàng, đào lên một đống đất sau đó xử lý nó để tìm ra NGUỒN VÀNG mà tôi muốn: 64K Cảm ơn nhiều.
SDsolar

10

Tôi đã tìm thấy kích thước khối tối ưu của mình là 8 MB (bằng với bộ nhớ cache của đĩa?) Tôi cần xóa (một số người nói: rửa) không gian trống trên đĩa trước khi tạo ảnh nén của nó. Tôi đã sử dụng:

cd /media/DiskToWash/
dd if=/dev/zero of=zero bs=8M; rm zero

Tôi đã thử nghiệm với các giá trị từ 4K đến 100M.

Sau khi để dd chạy một lúc, tôi đã giết nó (Ctlr + C) và đọc đầu ra:

36+0 records in
36+0 records out
301989888 bytes (302 MB) copied, 15.8341 s, 19.1 MB/s

Khi dd hiển thị tốc độ đầu vào / đầu ra (trong trường hợp này là 19,1MB / s), rất dễ dàng để xem liệu giá trị bạn đã chọn có hoạt động tốt hơn giá trị trước đó hay kém hơn.

Điểm của tôi:

bs=   I/O rate
---------------
4K    13.5 MB/s
64K   18.3 MB/s
8M    19.1 MB/s <--- winner!
10M   19.0 MB/s
20M   18.6 MB/s
100M  18.6 MB/s   

Lưu ý: Để kiểm tra kích thước bộ nhớ đệm / bộ đệm đĩa của bạn là bao nhiêu, bạn có thể sử dụng sudo hdparm -i /dev/sda


4
Bạn chỉ chạy mỗi bài kiểm tra một lần? Tôi nghĩ những gì bạn có thể thấy từ ≥64K là bộ đệm đã đầy và sự khác biệt chỉ là phương sai ngẫu nhiên.
Mads Y

Tôi đã từng nghe nói về các giá trị lớn có khả năng làm tắc nghẽn hệ thống. Người đó đang làm việc với một tệp lớn. Thật tuyệt nếu tôi có thể nghe thêm về điều này.
Todd Partridge

1
Kinh nghiệm của tôi cũng cho thấy 8Mrất khó để đánh bại.
Sridhar Sarnobat

Hấp dẫn. Bạn có nghĩ rằng điều này liên quan đến kích thước bộ nhớ cache L3 hay không? Tôi tự hỏi nếu kích thước khối lớn hơn bộ nhớ cache L3 sẽ chậm hơn.
SurpriseDog

3

Điều này hoàn toàn phụ thuộc vào hệ thống. Bạn nên thử nghiệm để tìm ra giải pháp tối ưu. Hãy thử bắt đầu với bs=8388608. (Vì ổ cứng của Hitachi dường như có bộ nhớ đệm 8MB.)


5
rất nhiều phiên bản dd chấp nhận shorthands: tức là bs=8Mtrên GNU / Linux hoặc bs=8mtrên BSD
pascal

4
lol, nghĩ rằng bạn sẽ nói "Hãy thử bắt đầu từ bs=8388608và giảm một lần mỗi bước"
lindhe 27/09/15

1
  • để có hiệu suất tốt hơn, hãy sử dụng kích thước khối lớn nhất mà RAM có thể chứa (sẽ gửi ít cuộc gọi I / O hơn đến hệ điều hành)
  • để có độ chính xác tốt hơn và khôi phục dữ liệu, hãy đặt kích thước khối thành kích thước khu vực gốc của đầu vào

Khi dd sao chép dữ liệu bằng tùy chọn đồng bộ hóa, chuyển đổi, bất kỳ lỗi nào mà nó gặp phải sẽ dẫn đến phần còn lại của khối được thay thế bằng không byte. Kích thước khối lớn hơn sẽ sao chép nhanh hơn, nhưng mỗi khi gặp lỗi, phần còn lại của khối sẽ bị bỏ qua.

nguồn


1
Tôi nghĩ rằng nếu có bất kỳ lỗi ghi nào, bạn nên thay thế phương tiện, không thay đổi kích thước khối ...
unfa
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.