Determinar el tamaño de bloque óptimo en dd

por | febrero 16, 2016

A colación del anterior post sobre cómo crear un USB de instalación con dd, pensé que sería interesante investigar acerca del mejor tamaño de bloque para optimizar la copia y ahorrar tiempo. La cuestión es que no hay una ciencia exacta al respecto, ya que el tamaño de bloque más adecuado depende del hardware que estemos utilizando.

Por lo tanto, lo que nos queda es hacer algún test que otro con el dispositivo con el que vamos a trabajar y tomar nota de los resultados.

Recordar que el primer paso es detectar el dispositivo en el que queremos escribir con lsblk y posteriormente tendremos que hacer el umount correspondiente. Esto es muy importante ya que si nos equivocamos de unidad podríamos perder datos o dejar el sistema inutilizado, por ejemplo en el caso de escribir en el disco que contiene la partición /boot o la raíz.

Por defecto el tamaño de bloque es de 512 bytes. Podemos probar una serie de tamaños de bloque para ver cuál es el más óptimo para nuestro dispositivo. En este caso, voy a probar mi USB, un Sandisk Extreme 3.0 de 16 GB que está en /dev/sdc. El siguiente script crea un fichero de prueba y posteriormente realiza sucesivas copias al dispositivo de destino mediante un bucle for. En cada iteración elige un tamaño de bloque en la secuencia que hayamos definido en la variable blocks_to_check:

#!/bin/bash
#
# Title         :dd_optimal_bs_test.sh
# Author        :Julio Sanz
# Website       :www.elarraydejota.com
# Email         :juliojosesb@gmail.com
# Tested in     :Debian Wheezy/Jessie, CentOS 7/6
# Description   :Script to check the optimal block size for a given device, useful to test with external drives
# Dependencies  :None
# Usage         :./dd_optimal_bs_test.sh
# License       :GPLv3
#
################################################################################

#============================
# VARIABLES
#============================

# Add as many as you want
blocks_to_check="1k 2k 4k 8k 16K 32K 64K 128K 256K 512K 1M 2M 4M 8M 16M"
# A temporary test file
test_file="/var/tmp/test_file"
# CAUTION! Check this variable output_destination carefully, dd will overwrite
# content of the device set as output_destination during this test
output_destination="/dev/sdc"
# To determine the size of the test file
count_n=128000

#============================
# MAIN
#============================

# Create test file
dd if=/dev/zero of=$test_file count=$count_n > /dev/null 2>&1

echo "---------Begin block size test----------"

for block_size in $blocks_to_check
do
        result=`dd if=$test_file of=$output_destination bs=$block_size 2>&1 1>/dev/null`
        time_spent=`echo $result | cut -d "," -f2`
        speed=`echo $result | cut -d "," -f3`
        echo "Block Size $block_size --- It took $time_spent --- Speed $speed"
done

# Remove test file
rm $test_file

Después de lanzar el script (comor root) obtengo:

---------Begin block size test----------
Block Size 1k --- It took  7.78363 s --- Speed  8.4 MB/s
Block Size 2k --- It took  7.73517 s --- Speed  8.5 MB/s
Block Size 4k --- It took  1.70712 s --- Speed  38.4 MB/s
Block Size 8k --- It took  1.71044 s --- Speed  38.3 MB/s
Block Size 16K --- It took  1.7197 s --- Speed  38.1 MB/s
Block Size 32K --- It took  1.69938 s --- Speed  38.6 MB/s
Block Size 64K --- It took  1.71692 s --- Speed  38.2 MB/s
Block Size 128K --- It took  1.73243 s --- Speed  37.8 MB/s
Block Size 256K --- It took  1.74178 s --- Speed  37.6 MB/s
Block Size 512K --- It took  1.72861 s --- Speed  37.9 MB/s
Block Size 1M --- It took  1.72915 s --- Speed  37.9 MB/s
Block Size 2M --- It took  1.73138 s --- Speed  37.9 MB/s
Block Size 4M --- It took  1.761 s --- Speed  37.2 MB/s
Block Size 8M --- It took  1.75742 s --- Speed  37.3 MB/s
Block Size 16M --- It took  1.7527 s --- Speed  37.4 MB/s

Está claro que para mi dispositivo USB el tamaño de bloque óptimo siempre tendrá que ser 4K o mayor. La velocidad de escritura crece enormemente, pasando de 8.5 MB/s con un tamaño de 2K a 38.4 MB/s con 4k. El bloque ideal sería en este caso 32K como podemos observar, con 38.6 MB/s