Por que o dd usa gravação mais lenta direta no disco do que em um arquivo?

7

Estou tentando comparar as taxas de gravação agregadas ao gravar em um arquivo em um sistema de arquivos GPFS, em comparação com a gravação direta em um disco em um sistema com o Red Hat Enterprise Linux Server versão 6.4 (Santiago). Para meu aplicativo, preciso medir a taxa bruta, ou seja, sem aproveitar o cache. Eu não entendo o impacto da opção direta usada com dd para ignorar o cache. Ao gravar diretamente em um dispositivo de bloco, obtenho uma taxa drasticamente menor quando uso oflag=direct , em comparação com a gravação em um arquivo no sistema de arquivos GPFS. Por que isso acontece?

Para medir as taxas agregadas, eu crio p processos executando dd que grava simultaneamente no dispositivo ou arquivo de bloco. Eu, então, somamos as p taxas obtidas para obter a taxa de gravação agregada.

    #!/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

Resultados: A taxa de gravação de cada um dos 30 processos é a seguinte:

  1. Gravando no disco usando a opção conv=fsync , cada processo obtém uma taxa de gravação de ~ 180MB / s
  2. Gravando no disco usando conv=fsync e oflag=direct , cada processo obtém uma taxa de gravação de ~ 9MB / s
  3. Gravar em um arquivo no sistema de arquivos GPFS, usando conv=fsync e oflag=direct , obtém uma taxa de gravação de ~ 80MB / s
por user3216949 21.01.2014 / 16:29

2 respostas

5

Esta diferença, sem dúvida, se resume a uma coisa: o armazenamento em cache.

Será realmente difícil determinar onde, especialmente a partir da userland, mas todas as escritas do sistema de arquivos do buffer (cache) dos kernels do Linux, a menos que você execute os truques para obter gravações síncronas. Ou seja, o kernel salvará os dados que o dd envia para um arquivo em algum lugar na memória do kernel. O kernel provavelmente usa o código do sistema de arquivos para fazer isso. Algum tempo no futuro, o kernel irá agendar um bloco de disco para ir para o disco. Isso acontecerá "de forma assíncrona", algum tempo depois que o kernel informar dd que a gravação terminou.

A razão para isso é que mover bytes em um barramento e em uma unidade de disco e, em seguida, nos discos é muito mais lento do que copiar do usuário para a memória do kernel. Normalmente, os programas não se importam muito com o fato de os dados que eles "escreveram" não chegarem ao disco por um tempo. A confiabilidade do hardware é alta o suficiente para que os dados façam isso quase sempre.

Essa é a resposta simples, mas uma vez que você tenha leituras / gravações / exclusões armazenadas em buffer no kernel, o código do sistema de arquivos pode tirar proveito de vidas úteis curtas, nunca escrevendo os dados dos arquivos que são deletados antes que eles sejam deletados. Faça isso no disco. O código do sistema de arquivos pode agrupar gravações para aproveitar os blocos de disco maiores que um grupo de gravações e consolidá-los em uma única gravação. Há toneladas de otimizações que podem ser feitas na maioria dos sistemas de arquivos.

    
por 21.01.2014 / 19:53
2

O armazenamento em cache de programas de cópia torna-o mais rápido do que o dd eu diria.

Se este é o único aplicativo intensivo de disco em execução, aguarde a saída do programa e execute:

$ sync; sync 

Isso irá liberar o cache imediatamente. Se demorar um pouco para retornar ao prompt, você sabe que ele está atingindo o cache.

Eu faço isso antes de puxar meus drives USB e, muitas vezes, leva muito tempo, desde o término da cópia até o cache que está batendo no disco.

    
por 22.01.2014 / 04:44