Toda sessão de troubleshooting de storage começa do mesmo jeito: você entra por SSH em uma máquina, abre as suas anotações (ou o histórico do navegador) e reconstrói o mesmo punhado de comandos fio que já rodou cem vezes. Leitura sequencial, escrita sequencial, leitura aleatória de 4K, R/W misto — cada um com tamanhos de bloco, profundidades de fila e quantidades de jobs ligeiramente diferentes, conforme o que você está caçando.
Essa estrutura repetitiva é exatamente o que o fio_benchmark elimina.
AVISO — ESTE SCRIPT ESCREVE DIRETAMENTE NO DISPOSITIVO DE BLOCO QUE VOCÊ ESPECIFICAR.
Apontá-lo para qualquer disco que contenha dados — o disco do seu SO, um volume montado, um datastore em uso — vai corromper ou destruir esses dados, imediatamente e sem nenhuma confirmação. Não há como desfazer.
Antes de executar, confirme o seu alvo com lsblk ou fdisk -l. Se /dev/sda é o seu disco de sistema, /dev/sdb é o datastore das suas VMs, ou você não tem 100% de certeza do que há no dispositivo, não execute este script contra ele. Use um disco de teste dedicado e em branco ou um arquivo de teste em um sistema de arquivos descartável (-t /mnt/testdir/testfile).
O que é (e o que não é)#
fio_benchmark é um wrapper em Bash em torno do fio. Ele não substitui o fio — nem tenta. O fio já é a ferramenta certa. O que ele faz é reunir os perfis de teste que a maioria dos sysadmins e profissionais de storage executa separadamente em uma única execução repetível, com parâmetros consistentes e saída estruturada que você realmente consegue comparar entre sistemas.
O público-alvo é simples: se você é sysadmin ou engenheiro de storage e precisa caracterizar rapidamente um dispositivo — seja um NVMe novo em um servidor bare-metal, uma LUN de SAN ou um disco de VM que você suspeita estar sendo limitado — isso leva você até lá sem montar a matriz de testes do zero toda vez.
Os 9 perfis que ele executa#
Todos os testes usam --direct=1, --ioengine=libaio e --group_reporting. Os testes aleatórios também desativam padrões repetidos (--randrepeat=0 --norandommap) para evitar artefatos de aquecimento de cache.
| # | Teste | Padrão | Tamanho de bloco | Jobs | iodepth | Tamanho |
|---|---|---|---|---|---|---|
| 1 | seqread | Leitura sequencial | 8k | 8 | 4 | 1G |
| 2 | seqwrite | Escrita sequencial | 32k | 4 | 4 | 2G |
| 3 | seq128kread | Leitura sequencial (BW máx.) | 128k | 8 | 4 | 2G |
| 4 | seq128kwrite | Escrita sequencial (BW máx.) | 128k | 4 | 4 | 2G |
| 5 | randread | Leitura aleatória | 8k | 16 | 8 | 1G |
| 6 | randwrite | Escrita aleatória | 64k | 8 | 8 | 512m |
| 7 | rand4kread | Leitura aleatória 4K | 4k | 16 | 8 | 1G |
| 8 | rand4kwrite | Escrita aleatória 4K | 4k | 8 | 8 | 1G |
| 9 | randrw | R/W aleatório (90% leitura) | 16k | 8 | 8 | 1G |
Para cada teste, ele coleta IOPS, largura de banda (MiB/s), latência média, desvio padrão da latência, percentis p50/p99/p99.9 e utilização de CPU. Também calcula uma razão de eficiência de IOPS por percentual de CPU — útil quando você compara um resultado bare-metal com uma VM rodando no mesmo hardware e quer quantificar o overhead do hypervisor.
Instalação#
Requisitos: Bash 4.4+, fio 3.0+, awk POSIX. Sem jq.
git clone https://github.com/9llo/fio_benchmark.git
chmod +x fio_benchmark/fio_benchmark.shExecutando#
A invocação mais simples contra um dispositivo de bloco (requer root):
sudo ./fio_benchmark.sh -t /dev/sdbSe você quiser fazer antes um dry-run, para verificar a configuração sem tocar no disco:
./fio_benchmark.sh -t /dev/sdb -nSem argumentos, você cai no modo interativo, que pergunta o alvo e o tempo de execução.
O formato de saída é texto simples por padrão. Para automação ou acompanhamento de longo prazo, use JSON ou CSV — as mensagens de progresso e de status sempre vão para o stderr, então a saída estruturada no stdout fica limpa para redirecionamento:
sudo ./fio_benchmark.sh -t /dev/sdb -o json > results.json
sudo ./fio_benchmark.sh -t /dev/sdb -o csv > results.csvO tempo de execução por teste é de 600 segundos por padrão. Para uma passada mais rápida durante a triagem inicial, você pode reduzi-lo:
sudo ./fio_benchmark.sh -t /dev/sdb -r 60As duas varreduras que realmente encontram gargalos#
Os perfis padrão dão uma linha de base. As varreduras é que diagnosticam por que um dispositivo se comporta como se comporta.
Varredura de iodepth (-s)#
Executa randread com bs=4k, numjobs=1 e percorre os valores de iodepth 1, 2, 4, 8, 16, 32, 64, 128.
sudo ./fio_benchmark.sh -t /dev/sdb -sA curva de IOPS mostra onde o paralelismo interno do dispositivo satura. Um NVMe de consumo normalmente estabiliza por volta de iodepth 8–16. Um SSD empresarial ou uma LUN de SAN com uma fila de comandos profunda pode continuar subindo bem além de 32. Se você vê o IOPS estabilizar cedo e depois degradar, isso costuma ser um problema de firmware ou de gerenciamento de fila que vale a pena investigar.
Varredura de mix R/W (-m)#
Executa randrw com bs=4k, numjobs=8, iodepth=8, variando o percentual de escrita de 0% a 100% em passos de 10%.
sudo ./fio_benchmark.sh -t /dev/sdb -mIsso mapeia a curva de penalidade de escrita. Em um NVMe saudável, o IOPS deve degradar de forma razoavelmente gradual conforme o % de escrita aumenta. Em um SSD muito superprovisionado perto da capacidade, ou em um datastore thin-provisioned sendo supercomprometido, a curva despenca quando as escritas começam a disparar garbage collection e amplificação de escrita. Se você roda um banco de dados e se pergunta por que o desempenho despenca sob cargas pesadas em escrita, esta varredura vai mostrar.
Exemplo de saída (texto)#
Device: /dev/sdb | Samsung SSD 870 QVO | SSD | 1000GB | 512B blocks | mq-deadline
┌──────────────────┬──────────┬──────────┬────────────┬────────────┬────────────┬────────────┬────────────┬───────┬───────┬──────────────┐
│ Test │ IOPS │ BW MB/s │ Lat avg │ Lat std │ p50 │ p99 │ p99.9 │ CPU u │ CPU s │ IOPS/CPU% │
├──────────────────┼──────────┼──────────┼────────────┼────────────┼────────────┼────────────┼────────────┼───────┼───────┼──────────────┤
│ seqread │ 52341 │ 409.7 │ 0.61 ms │ 0.12 ms │ 0.58 ms │ 0.94 ms │ 1.24 ms │ 3.1% │ 2.1% │ 10018.7 │
│ seqwrite │ 14832 │ 462.9 │ 1.08 ms │ 0.31 ms │ 0.99 ms │ 1.97 ms │ 3.51 ms │ 2.2% │ 1.8% │ 3707.8 │
...Quando usar#
- Qualificar hardware de storage novo antes de ele entrar em produção
- Comparar o desempenho do disco de uma VM com o de bare-metal para medir o overhead de virtualização
- Verificar se uma reclamação de “storage lento” de uma equipe de aplicação é real ou uma pista falsa
- Montar uma linha de base antes e depois de uma atualização de firmware ou de uma mudança na configuração de storage
- Investigar um SSD que parece mais lento do que o esperado após meses de uso (desgaste e amplificação de escrita)
Ele não vai dizer por que algo está lento por conta própria — isso ainda exige interpretação. Mas ter a matriz de testes completa, com parâmetros consistentes, em menos de uma hora, é um ponto de partida melhor do que montá-la à mão toda vez.
Uma palavra sobre como isso foi construído#
Transparência total: boa parte da iteração neste script foi feita com o Claude Code como par de programação.
O conhecimento de domínio — quais testes importam, quais tamanhos de bloco usar para cada perfil de carga, por que a varredura de iodepth é mais útil do que rodar uma única profundidade de fila, como fazer o parse da saída JSON do fio sem trazer o jq como dependência — tudo isso veio de anos de troubleshooting real de storage. O Claude não sabia que randrepeat=0 importa para evitar artefatos de aquecimento de cache, nem que uma razão de eficiência de IOPS por CPU é útil especificamente em ambientes de VM. Esse contexto precisou ser fornecido.
O que ele acelerou: o boilerplate em Bash que ninguém gosta de escrever. O parser de argumentos, os traps de limpeza, o wrapper de timeout em volta de cada chamada ao fio, a passada de awk que extrai os campos de percentil do JSON sem dependência. Coisas tediosas e propensas a erro para acertar, mas nada intelectualmente interessante depois que você sabe o que elas precisam fazer.
O resumo honesto: ele transformou uma tarefa que seria um fim de semana inteiro de hacking intermitente em uma noite focada. O raciocínio não foi terceirizado — foi destravado.
A IA não vai substituir sysadmins nem engenheiros de storage. Ela não faz ideia de como é a topologia da sua SAN, por que a sua latência dispara às 3h da manhã, ou o que “estava tudo bem antes da atualização de firmware” realmente significa no contexto. Mas se você consegue descrever com precisão o que quer, ela é uma colaboradora notavelmente boa para as partes do trabalho que são apenas execução. Quem descobrir como usá-la bem não vai ser substituído — vai render mais.
O repositório está em github.com/9llo/fio_benchmark. Issues e PRs estão abertos.

