2011-05-28 107 views
81

运行dd时,如何计算最佳块大小?我已经研究了一下,我还没有发现任何暗示这将如何完成的事情。dd:如何计算最佳块大小?

我的印象是,较大的块大小会导致更快的速度dd ......这是真的吗?

我即将dd两个完全相同的500GB日立硬盘,运行速度为7200rpm,运行带有4GB DDR3 1333MHz内存的英特尔酷睿i3处理器,所以我试图找出需要使用的块大小。 (我将从闪存驱动器启动Ubuntu 10.10 x86,并从中运行它。)

回答

71

最佳块大小取决于各种因素,包括操作系统(及其版本)以及各种硬件巴士和磁盘。一些类Unix系统(包括Linux和至少BSD的一些风格)定义在struct statst_blksize成员,使该内核认为什么是最佳块大小:

#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做得很好,例如64 KiB和1 MiB之间的差异较小,而4 KiB与64之间的差异较小昆明植物研究所。 (虽然,虽然已经有一段时间了,但我现在默认使用mebibyte,或者只是让dd选择大小。)

+7

我很抱歉没有接受过这个答案......谢谢! – eckza 2012-04-01 02:28:54

+0

关于记住删除缓存的优点。这搞乱了我的测量! (虽然小问题:它是“drop_caches”,带有下划线,显然编辑至少需要6个字符...... :() – Tom 2015-12-09 17:10:11

3

这完全取决于系统。您应该尝试找到最佳解决方案。 尝试从bs=8388608开始。 (因为日立硬盘似乎有8MB缓存。)

+3

许多dd版本接受shorthands:即GNU/Linux上的'bs = 8M'或' bs = 8m'在BSD – pascal 2014-04-30 20:05:14

+1

lol,以为你会说“尝试从'bs = 8388608'开始,每一步递减一次” – lindhe 2015-09-27 20:00:12

4

你可以尝试使用dd-opt,我写的一个小工具。

(改善/改进的欢迎!)

+1

Woah - 它是用Ruby编写的?很好!我一定会给它一个旋转! – eckza 2012-04-26 22:05:41

+11

目前(2012-08-09),除了Mac OS X以外,dd-opt还没有在操作系统上工作。 – Henno 2012-08-09 10:52:15

0
  • 更好的服务表现使用您的RAM可容纳的最大块大小(将发送更少的I/O调用操作系统)
  • 更好accurancy和数据恢复集块大小与输入的原始扇区大小

如同CONV = NOERROR DD拷贝数据,同步选项,它遇到将导致该块的剩余部分的任何错误被替换为零字节。较大的块大小会更快地复制,但每次遇到错误时,块的其余部分都会被忽略。

source

6

我发现我的最佳块大小为8 MB,我需要擦拭(有人说:洗)(等于磁盘缓存?)创建压缩图像之前磁盘上的空白空间的。 我使用过:

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 
+1

你是否只运行一次测试?我认为你可能从≥64K看到的是,缓冲区是已经满了,差别只是随机差异 – 2015-08-23 09:37:10

+0

我曾经听说过一次大的值可能会阻碍系统,这个人正在处理一个大文件,如果我能听到更多关于这个的信息,那将是很好的。 – 2017-03-14 13:45:11

+0

我的经验也表明'8M'很难被击败。 – 2017-07-17 17:49:45

44

正如其他人所说,没有普遍正确的块大小;对于一种情况或一件硬件来说最佳的可能对另一种情况来说是非常低效的。另外,根据磁盘的健康状况,最好使用与“最优”不同的块大小。

在现代硬件上非常可靠的一件事是,512字节的默认块大小几乎比一个更优化的替代方案慢一个数量级。如果有疑问,我发现64K是一个非常坚实的现代默认设置。虽然64K通常不是最佳的块大小,但根据我的经验,它往往比默认的效率更高。 64K在可靠性方面也有着非常可靠的历史:你可以从Eug-Lug邮件列表中找到一条消息,大约在2002年,建议这里的块大小为64K:http://www.mail-archive.com/[email protected]/msg12073.html

为了确定最佳输出块大小,已经写了下面的脚本,测试用dd在不同块大小的范围内编写128M测试文件,从默认的512字节到最大64M。被警告,这个脚本在内部使用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 

View on GitHub

我只测试了这个脚本在Debian(Ubuntu的)系统和OSX优山美地,所以它可能会采取一些调整,使工作其他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读取/零和写在磁盘上,您可以从 中读取磁盘并写入/ 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 

View on GitHub

在这种情况下,一个重要的区别是,测试文件是由脚本编写的文件。不要将此命令指向现有文件,否则现有文件将被零覆盖!

对于我的特定硬件,我发现128K是硬盘上最优化的输入块大小,32K最适合SSD。

虽然这个答案涵盖了我的大部分发现,但我已经遇到过这种情况,我已经写了一篇关于它的博客文章:http://blog.tdg5.com/tuning-dd-block-size/您可以在我在那里进行的测试中找到更多细节。

+0

我已经运行了第二个脚本,测试了读取性能,并在2015年rMBP上安装了512G SSD。最佳块大小为8388608:3.582 GB字节/秒。 – 2016-03-01 16:19:45

+0

更正:我已经运行了第二个脚本,测试了读取性能,使用512GB SSD的2015年rMBP。最佳块大小为524288(5.754 GB /秒)。第二好的块大小是131072(5.133 GB /秒)。 (我在为最后一条评论生成值时错误地对结果进行了排序。) – 2016-03-01 16:32:07

+0

对于'dd_obs_test.sh'“conv = fsync”在macOS上不起作用,可以将其删除。 – rynop 2017-05-19 03:45:23