dd : 최적의 블록 크기를 계산하는 방법은 무엇입니까? [닫은]


122

를 실행할 때 최적의 블록 크기를 어떻게 계산 dd합니까? 나는 그것을 조금 조사했지만 이것이 어떻게 성취 될 것인지 제안하는 것을 발견하지 못했습니다.

나는 더 큰 블록 크기가 더 빨라질 것이라는 인상을 받고 있습니다 dd...이게 사실입니까?

dd4GB DDR3 1333mhz RAM이 장착 된 Intel Core i3를 실행하는 상자에서 7200rpm으로 실행 되는 두 개의 동일한 500GB Hitachi HDD가 있으므로 사용할 블록 크기를 알아 내려고합니다. (저는 플래시 드라이브에서 Ubuntu 10.10 x86을 부팅하고 거기에서 실행할 것입니다.)


macOS 용 @ tdg5 답변 채택 -macos_dd_ibs_test.shmacos_dd_obs_test.sh
mixel 19

1
가장 좋은 대답은 dd파일을 전송하는 동안 최적의 블록 크기를 찾는 기능을 제공하는 것입니다
Boris

이 주제가 표시되고 수퍼 유저로 마이그레이션되지 않은 이유는 무엇입니까?
user267092

답변:


95

최적의 블록 크기는 운영 체제 (및 해당 버전) 및 관련된 다양한 하드웨어 버스 및 디스크를 포함한 다양한 요인에 따라 다릅니다. 여러 유닉스 계열 시스템 (리눅스 및 BSD의 일부 버전 포함) st_blksizestruct stat 은 커널이 최적의 블록 크기라고 생각 것을 제공 .

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

int main(void)
{
    struct stat stats;

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

가장 좋은 방법은 실험하는 것입니다. 다양한 블록 크기와 시간으로 기가 바이트를 복사합니다. (각 실행 전에 커널 버퍼 캐시를 지우는 것을 잊지 마십시오 :echo 3 > /proc/sys/vm/drop_caches .

그러나 경험상 충분히 큰 블록 크기 dd는 좋은 작업을 수행 할 수 있으며, 예를 들어 64KiB와 1MiB의 차이는 4KiB 대 64KiB에 비해 미미 하다는 것을 알았습니다 . (확실히 그렇게 한 지 오래되었습니다. 지금은 기본적으로 메비 바이트를 사용하거나 dd크기를 선택 하겠습니다 .)


11
이 질문을 답으로 받아들이지 않아서 정말 죄송합니다 ... 감사합니다!
eckza

캐시 삭제 기억에 대한 훌륭한 포인트. 이것은 내 측정을 엉망으로 만들었습니다! (사소한 문제이지만, 밑줄이있는 "drop_caches"입니다. 분명히 편집은 6 자 이상이어야합니다 ... :()
Tom

73

다른 사람들이 말했듯이 보편적으로 올바른 블록 크기는 없습니다. 어떤 상황이나 하드웨어에 최적 인 것이 다른 상황에서는 매우 비효율적 일 수 있습니다. 또한 디스크의 상태에 따라 "최적"블록 크기와 다른 블록 크기를 사용하는 것이 좋습니다.

최신 하드웨어에서 상당히 신뢰할 수있는 한 가지는 기본 블록 크기 인 512 바이트가 최적의 대안보다 거의 10 배 더 느리다는 것입니다. 의심 스러울 때 나는 64K가 매우 견고한 현대 기본값이라는 것을 발견했습니다. 64K가 일반적으로 최적의 블록 크기는 아니지만 내 경험상 기본값보다 훨씬 더 효율적인 경향이 있습니다. 64K는 또한 안정적인 성능을 보여준 꽤 ​​견고한 역사를 가지고 있습니다. 2002 년경 Eug-Lug 메일 링리스트에서 64K 블록 크기를 권장하는 메시지를 찾을 수 있습니다. http://www.mail-archive.com/eug- lug@efn.org/msg12073.html

최적의 출력 블록 크기를 결정하기 위해 기본 512 바이트에서 최대 64M까지 다양한 블록 크기 범위에서 dd로 128M 테스트 파일 작성을 테스트하는 다음 스크립트를 작성했습니다. 이 스크립트는 내부적으로 dd를 사용하므로주의해서 사용하십시오.

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

GitHub에서보기

이 스크립트는 Debian (Ubuntu) 시스템과 OSX Yosemite에서만 테스트했기 때문에 다른 Unix 버전에서 작업하려면 약간의 조정이 필요할 것입니다.

기본적 으로이 명령은 현재 디렉토리에 dd_obs_testfile 이라는 테스트 파일을 생성합니다 . 또는 스크립트 이름 뒤에 경로를 제공하여 사용자 정의 테스트 파일의 경로를 제공 할 수 있습니다.

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

스크립트의 출력은 테스트 된 블록 크기 및 각각의 전송 속도 목록입니다.

$ ./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

(참고 : 전송 속도의 단위는 OS에 따라 다릅니다)

최적의 읽기 블록 크기를 테스트하려면 동일한 프로세스를 어느 정도 사용할 수 있지만 / dev / zero에서 읽고 디스크에 쓰는 대신 디스크에서 읽고 / dev / null에 씁니다. 이를 수행하는 스크립트는 다음과 같습니다.

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

GitHub에서보기

이 경우 중요한 차이점은 테스트 파일이 스크립트로 작성된 파일이라는 것입니다. 이 명령을 기존 파일을 가리 키지 마십시오. 그렇지 않으면 기존 파일을 0으로 덮어 씁니다!

내 특정 하드웨어의 경우 128K가 HDD에서 가장 최적의 입력 블록 크기이고 32K가 SSD에서 가장 최적이라는 것을 알았습니다.

이 답변은 내 발견의 대부분을 다루지 만, 나는 이에 대한 블로그 게시물을 썼을 정도로이 상황에 충분히 부딪 쳤 습니다. http://blog.tdg5.com/tuning-dd-block-size/ 더 자세한 내용을 찾을 수 있습니다. 내가 거기에서 수행 한 테스트에서.


1
저는 512G SSD를 사용하는 2015 rMBP에서 읽기 성능을 테스트하는 두 번째 스크립트를 실행했습니다. 최고의 블록 크기는 8388608 : 3.582GB / 초입니다.
Quinn Comendant

1
수정 : 512GB SSD를 사용하는 2015 rMBP에서 읽기 성능을 테스트하는 두 번째 스크립트를 실행했습니다. 최고의 블록 크기는 524288 (5.754GB / 초)입니다. 두 번째로 좋은 블록 크기는 131072 (5.133GB / 초)입니다. (마지막 댓글에 대한 값을 생성 할 때 결과를 잘못 정렬했습니다.)
퀸 Comendant

에 대한 dd_obs_test.sh conv=fsync 는 macOS에서 작동하지 않으며 제거 할 수 있습니다.
rynop

제 경험상, 더 큰 블록 크기를 벤치마킹하려면 더 큰 샘플이 필요합니다 (몇 초. 128MB 파일로 만들 수 있다고 생각하지만 확실하지 않습니다). 이유가 확실하지 않습니다.
Rolf

2
친구! 정말 놀라운 대답입니다. 그것은 금광을 찾고, 많은 흙을 파 내고 내가 원하는 금 덩어리를 찾기 위해 처리하는 것과 같습니다. 64K 감사합니다.
SDsolar

10

최적의 블록 크기가 8MB (디스크 캐시와 같습니까?)라는 것을 알았습니다. 압축 된 이미지를 만들기 전에 디스크의 빈 공간을 닦아야했습니다 (일부는 세척). 나는 다음을 사용했다 :

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

4K에서 100M까지의 값을 실험했습니다.

dd가 잠시 실행되도록 한 후 나는 그것을 죽이고 (Ctlr + C) 출력을 읽었습니다.

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

dd는 입력 / 출력 속도 (이 경우 19.1MB / s)를 표시하므로 선택한 값이 이전 값보다 더 나은지 또는 더 나쁜지 쉽게 확인할 수 있습니다.

내 점수 :

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   

참고 : 디스크 캐시 / 버퍼 크기를 확인하려면 다음을 사용할 수 있습니다. sudo hdparm -i /dev/sda


4
각 테스트를 한 번만 실행 했습니까? 64K 이상에서 볼 수있는 것은 버퍼가 이미 꽉 찼고 그 차이는 무작위 분산이라는 것입니다.
Mads Y

큰 값이 잠재적으로 시스템에 병목 현상을 일으킬 수 있다는 이야기를 들었습니다. 그 사람은 큰 파일로 작업하고있었습니다. 이것에 대해 더들을 수 있다면 좋을 것입니다.
토드 파트 리지

1
내 경험 역시 8M이길 수 없다는 것을 암시 합니다.
Sridhar Sarnobat

흥미 롭군. 이것이 L3 캐시 크기와 관련이 있다고 생각하십니까? L3 캐시보다 큰 블록 크기가 느려질 지 궁금합니다.
SurpriseDog

3

이것은 전적으로 시스템에 따라 다릅니다. 최적의 솔루션을 찾기 위해 실험을해야합니다. 로 시작해보십시오 bs=8388608. (Hitachi HDD에는 8MB 캐시가있는 것 같습니다.)


5
많은 dd 버전은 속기 사용 : 즉 bs=8MGNU / Linux 또는 bs=8mBSD
pascal

4
롤, 당신이 "시작하고 bs=8388608매 단계마다 한 번씩 감소 시도"라고 말할 줄 알았는데
lindhe

1
  • 더 나은 성능을 위해 RAM이 수용 할 수있는 가장 큰 블록 크기를 사용하십시오 (OS에 더 적은 I / O 호출을 보낼 것임).
  • 더 나은 정확성과 데이터 복구를 위해 블록 크기를 입력의 기본 섹터 크기로 설정하십시오.

dd는 conv = noerror, sync 옵션을 사용하여 데이터를 복사 할 때 오류가 발생하면 블록의 나머지 부분이 0 바이트로 대체됩니다. 블록 크기가 클수록 더 빨리 복사되지만 오류가 발생할 때마다 나머지 블록은 무시됩니다.

출처


1
나는 어떤 쓰기 오류가있는 경우 ... 블록 크기를 변경하지, 매체를 교체해야한다고 생각
unfa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.