Problema
Instalei recentemente um novo disco e criei um zpool nele:
/# zpool create morez /dev/sdb
Depois de usá-lo por um tempo, notei que era bastante lento:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
write: IOPS=19.6k, BW=76.6MiB/s (80.3MB/s)(5120MiB/66834msec)
Este teste é bastante semelhante ao meu caso de uso real. Estou lendo um número moderado (~ 10k) de imagens (~ 2 MiB cada) do disco. Eles foram gravados de uma só vez quando o disco estava praticamente vazio, portanto, não espero que estejam fragmentados.
Para comparação, testei o ext4:
/# gdisk /dev/sdb
...
/# mkfs.ext4 -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
write: IOPS=48.3k, BW=189MiB/s (198MB/s)(5120MiB/27135msec)
E btrfs:
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# fio --name rw --rw rw --size 10G
read: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
write: IOPS=51.3k, BW=201MiB/s (210MB/s)(5120MiB/25528msec)
O que pode estar causando problemas de desempenho no ZFS e como posso torná-lo mais rápido?
Falha na tentativa de solução
Também tentei definir explicitamente o tamanho do setor para o zpool, pois meu disco ( Seagate ST1000DM003 ) usa setores físicos de 4096 bytes:
/# zpool create -o ashift=12 morez /dev/sdb
Isso não melhorou o desempenho:
/morez# fio --name rw --rw rw --size 10G
read: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
write: IOPS=21.3k, BW=83.2MiB/s (87.2MB/s)(5120MiB/61573msec)
Observação
Estranhamente, o uso de um zvol teve um ótimo desempenho:
/# zfs create -V 20G morez/vol
/# fio --name rw --filename /dev/zvol/morez/vol --rw rw --size 10G
read: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
write: IOPS=52.7k, BW=206MiB/s (216MB/s)(5120MiB/24852msec)
Por que isso afeta apenas os sistemas de arquivos ZFS e não os zvols?
Teste estendido para btrfs
Nos comentários, foi sugerido que a diferença pode ser devido ao cache. Após mais testes, não acredito que seja esse o caso. Aumentei o tamanho do teste btrfs bem acima da quantidade de memória que meu computador possui e seu desempenho ainda era significativamente maior que o do ZFS:
/# mkfs.btrfs -f /dev/sdb1 && mount /dev/sdb1 /mnt && cd /mnt
/mnt# $ fio --name rw --rw rw --size 500G --runtime 3600 --time_based --ramp_time 900
read: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
write: IOPS=41.9k, BW=164MiB/s (172MB/s)(576GiB/3600003msec)
Informação do sistema
Programas
- Arch Linux, versão do kernel 4.11.6
- ZFS no Linux 0.6.5.10
- fio 2.21
Hardware
- Unidade sendo testada: Seagate ST1000DM003 , conectado à porta SATA de 6 Gb / s
- Placa-mãe: Gigabyte X99-SLI
- Memória: 8 GiB
Informações do ZFS
Aqui está como eram as propriedades do ZFS antes de executar o fio. Estes são apenas o resultado da criação de um zpool com as configurações padrão.
# zpool get all morez
NAME PROPERTY VALUE SOURCE
morez size 928G -
morez capacity 0% -
morez altroot - default
morez health ONLINE -
morez guid [removed] default
morez version - default
morez bootfs - default
morez delegation on default
morez autoreplace off default
morez cachefile - default
morez failmode wait default
morez listsnapshots off default
morez autoexpand off default
morez dedupditto 0 default
morez dedupratio 1.00x -
morez free 928G -
morez allocated 276K -
morez readonly off -
morez ashift 0 default
morez comment - default
morez expandsize - -
morez freeing 0 default
morez fragmentation 0% -
morez leaked 0 default
morez feature@async_destroy enabled local
morez feature@empty_bpobj enabled local
morez feature@lz4_compress active local
morez feature@spacemap_histogram active local
morez feature@enabled_txg active local
morez feature@hole_birth active local
morez feature@extensible_dataset enabled local
morez feature@embedded_data active local
morez feature@bookmarks enabled local
morez feature@filesystem_limits enabled local
morez feature@large_blocks enabled local
# zfs get all morez
NAME PROPERTY VALUE SOURCE
morez type filesystem -
morez creation Thu Jun 29 19:34 2017 -
morez used 240K -
morez available 899G -
morez referenced 96K -
morez compressratio 1.00x -
morez mounted yes -
morez quota none default
morez reservation none default
morez recordsize 128K default
morez mountpoint /morez default
morez sharenfs off default
morez checksum on default
morez compression off default
morez atime on default
morez devices on default
morez exec on default
morez setuid on default
morez readonly off default
morez zoned off default
morez snapdir hidden default
morez aclinherit restricted default
morez canmount on default
morez xattr on default
morez copies 1 default
morez version 5 -
morez utf8only off -
morez normalization none -
morez casesensitivity sensitive -
morez vscan off default
morez nbmand off default
morez sharesmb off default
morez refquota none default
morez refreservation none default
morez primarycache all default
morez secondarycache all default
morez usedbysnapshots 0 -
morez usedbydataset 96K -
morez usedbychildren 144K -
morez usedbyrefreservation 0 -
morez logbias latency default
morez dedup off default
morez mlslabel none default
morez sync standard default
morez refcompressratio 1.00x -
morez written 96K -
morez logicalused 72.5K -
morez logicalreferenced 40K -
morez filesystem_limit none default
morez snapshot_limit none default
morez filesystem_count none default
morez snapshot_count none default
morez snapdev hidden default
morez acltype off default
morez context none default
morez fscontext none default
morez defcontext none default
morez rootcontext none default
morez relatime off default
morez redundant_metadata all default
morez overlay off default
fonte
/etc/modprobe.d/zfs.conf
man 5 zfs-module-parameters
.Respostas:
Enquanto velho, sinto que esta pergunta merece uma resposta.
fio
emite, por padrão, IOPs do tamanho de 4KB; Os conjuntos de dados do ZFS, em vez disso, usam 128 KB de gravação por padrão. Essa incompatibilidade significa que cada gravação em 4K causa uma leitura / modificação / gravação de todo o registro de 128K.Os ZVOLs, por outro lado, usam tamanho de bloco de 8K por padrão. Isso significa que uma gravação em 4K causa um ciclo de leitura / modificação / gravação muito menor de um registro de 8K e, com alguma sorte, duas gravações em 4K podem ser combinadas em uma única gravação de 8K (que não requer leitura / modificação / gravação).
O
zfs set recordize=8K <dataset>
tamanho do registro do conjunto de dados do ZFS pode ser alterado e, nesse caso, deve fornecer um desempenho mais ou menos equivalente aos ZVOLs. No entanto, quando usado para transferências relativamente grandes (o OP falou sobre arquivos de 2 MB que, sendo imagens, devem ser lidos inteiramente toda vez que forem acessados), é melhor ter um tamanho de registro / volume grande , às vezes até maior que a configuração padrão (128K).fonte
Nota: como o trabalho do fio não possui
direct=1
( http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-direct ), uma certa quantidade de E / S que está sendo executada (leitura e gravação) pode ser armazenada em cache pelo sistema operacional, distorcendo seus resultados (e aumentando os números artificialmente). Isso por si só é ainda mais complicado pelo seguinte:O_DIRECT
(portanto, a abertura falha) ou, se o fizer, faz isso silenciosamente voltando à E / S em buffer (consulte o ponto 3 de https://github.com/zfsonlinux/zfs/commit / a584ef26053065f486d46a7335bea222cb03eeea ).O_DIRECT
retornam à E / S em buffer.Esteja ciente de que
O_DIRECT
ainda é permitido fazer E / S em buffer porque no LinuxO_DIRECT
é mais uma dica (consulte a seção de referências em /programming//a/46377629/2732969 ).Se você estiver em uma situação em que não pode ignorar corretamente os caches, é crucial que você faça E / S suficientes em uma área grande o suficiente para minimizar o impacto do cache (a menos, é claro, que você realmente queira testar o cache) ...
fonte