SCRIPT ANÁLISE PERFORMANCE
bash
cat >/root/arc-monitor.sh <<'EOF'
#!/usr/bin/env bash
#
# =============================================================================
# ARC / L2ARC MONITOR - TrueNAS SCALE / OpenZFS
# =============================================================================
#
# OBJETIVO
# Medir a eficiência do ARC e L2ARC durante uma janela real de utilização.
#
# O script NÃO gera carga no pool e NÃO altera parâmetros do ZFS.
# Apenas lê contadores do kernel e calcula a diferença entre dois momentos.
#
#
# USO BÁSICO
#
# 1) Iniciar uma nova janela:
#
# /root/arc-monitor.sh start
#
# 2) Deixar o storage trabalhar normalmente por 30-60 minutos
# ou durante o período que deseja analisar.
#
# 3) Mostrar o relatório:
#
# /root/arc-monitor.sh report
#
# O "report" pode ser executado várias vezes.
# Todos os relatórios continuam usando o último "start" como início.
#
# Para zerar a medição:
#
# /root/arc-monitor.sh start
#
#
# OUTROS COMANDOS
#
# /root/arc-monitor.sh thresholds
# /root/arc-monitor.sh glossary
# /root/arc-monitor.sh help
#
#
# CORES
#
# As cores são ativadas automaticamente quando a saída é um terminal.
#
# Para desativar:
#
# NO_COLOR=1 /root/arc-monitor.sh report
#
# Ao redirecionar para arquivo, as cores são removidas automaticamente:
#
# /root/arc-monitor.sh report > /tmp/arc-report.txt
#
#
# ARQUIVOS LIDOS
#
# /proc/spl/kstat/zfs/arcstats
# /proc/meminfo
#
# SNAPSHOT
#
# /tmp/arc-monitor-before.txt
#
#
# INDICADOR PRINCIPAL
#
# O principal indicador utilizado é DEMAND DATA MISS.
#
# Ele representa dados pedidos diretamente pelas aplicações que
# não foram encontrados no ARC.
#
# <= 2% EXCELENTE
# <= 5% BOM
# <= 10% ATENCAO
# > 10% RUIM
#
# O ARC Total é apenas contexto secundário.
#
# =============================================================================
set -u
STATS="/proc/spl/kstat/zfs/arcstats"
STATE="/tmp/arc-monitor-before.txt"
# =============================================================================
# THRESHOLDS
# =============================================================================
DD_EXCELLENT_MAX=2
DD_GOOD_MAX=5
DD_WARN_MAX=10
L2_EXCELLENT_MIN=40
L2_GOOD_MIN=25
L2_WARN_MIN=10
MIN_DEMAND_SAMPLES=10000
MIN_L2_SAMPLES=1000
MRU_WARN_MIN=90
MRU_BAD_MIN=95
L2_LOW_FOR_POLLUTION=20
# =============================================================================
# CORES
# =============================================================================
if [[ -t 1 && -z "${NO_COLOR:-}" ]]; then
RESET=$'\033[0m'
BOLD=$'\033[1m'
DIM=$'\033[2m'
RED=$'\033[31m'
GREEN=$'\033[32m'
YELLOW=$'\033[33m'
BLUE=$'\033[34m'
CYAN=$'\033[36m'
BRIGHT_RED=$'\033[91m'
BRIGHT_GREEN=$'\033[92m'
BRIGHT_YELLOW=$'\033[93m'
BRIGHT_BLUE=$'\033[94m'
BRIGHT_CYAN=$'\033[96m'
else
RESET=""
BOLD=""
DIM=""
RED=""
GREEN=""
YELLOW=""
BLUE=""
CYAN=""
BRIGHT_RED=""
BRIGHT_GREEN=""
BRIGHT_YELLOW=""
BRIGHT_BLUE=""
BRIGHT_CYAN=""
fi
# =============================================================================
# FORMATAÇÃO VISUAL
# =============================================================================
line() {
printf '%s%s%s\n' \
"$CYAN" \
"==============================================================================" \
"$RESET"
}
subline() {
printf '%s%s%s\n' \
"$DIM" \
"------------------------------------------------------------------------------" \
"$RESET"
}
section() {
echo
subline
printf '%s%s %s%s\n' \
"$BOLD" \
"$BRIGHT_CYAN" \
"$1" \
"$RESET"
subline
}
status_color() {
local status="$1"
case "$status" in
EXCELENTE*)
printf '%s%s%s%s' \
"$BOLD" "$BRIGHT_GREEN" "$status" "$RESET"
;;
BOM*)
printf '%s%s%s' \
"$GREEN" "$status" "$RESET"
;;
ATENCAO*)
printf '%s%s%s%s' \
"$BOLD" "$YELLOW" "$status" "$RESET"
;;
RUIM*)
printf '%s%s%s%s' \
"$BOLD" "$BRIGHT_RED" "$status" "$RESET"
;;
AMOSTRA*)
printf '%s%s%s' \
"$BRIGHT_BLUE" "$status" "$RESET"
;;
INCONCLUSIVO*)
printf '%s%s%s' \
"$BRIGHT_BLUE" "$status" "$RESET"
;;
OK*)
printf '%s%s%s' \
"$GREEN" "$status" "$RESET"
;;
"FORTE INDICIO"*)
printf '%s%s%s%s' \
"$BOLD" "$BRIGHT_RED" "$status" "$RESET"
;;
POSSIVEL*)
printf '%s%s%s' \
"$YELLOW" "$status" "$RESET"
;;
"NAO EVIDENTE"*)
printf '%s%s%s' \
"$GREEN" "$status" "$RESET"
;;
*)
printf '%s' "$status"
;;
esac
}
# =============================================================================
# LEITURA DOS CONTADORES
# =============================================================================
get_stat() {
local v
v=$(
awk -v n="$1" '
$1 == n {
print $3
exit
}
' "$STATS" 2>/dev/null || true
)
printf '%s\n' "${v:-0}"
}
get_memavailable_bytes() {
awk '
$1 == "MemAvailable:" {
printf "%.0f\n", $2 * 1024
exit
}
' /proc/meminfo
}
snapshot() {
echo "timestamp=$(date +%s)"
echo "date=$(date -Is)"
echo "host=$(hostname)"
echo "mem_available=$(get_memavailable_bytes)"
for x in \
size \
c \
c_max \
memory_available_bytes \
hits \
iohits \
misses \
demand_data_hits \
demand_data_iohits \
demand_data_misses \
l2_hits \
l2_misses \
l2_size \
l2_asize \
l2_write_bytes \
l2_abort_lowmem \
l2_mru_asize \
l2_mfu_asize \
l2_prefetch_asize
do
echo "$x=$(get_stat "$x")"
done
}
value() {
local file="$1"
local key="$2"
awk -F= -v k="$key" '
$1 == k {
print substr($0,index($0,"=")+1)
exit
}
' "$file"
}
num_or_zero() {
if [[ "$1" =~ ^-?[0-9]+$ ]]; then
printf '%s\n' "$1"
else
printf '0\n'
fi
}
delta() {
local key="$1"
local a
local b
a=$(num_or_zero "$(value "$STATE" "$key")")
b=$(num_or_zero "$(value "$CURRENT" "$key")")
echo $((b - a))
}
# =============================================================================
# CONVERSÕES
# =============================================================================
pct_num() {
awk -v n="$1" -v d="$2" '
BEGIN {
if (d <= 0)
print "-1"
else
printf "%.4f", (n/d)*100
}
'
}
pct_fmt() {
awk -v p="$1" '
BEGIN {
if (p < 0)
printf "N/A"
else
printf "%.2f%%", p
}
'
}
human_count() {
awk -v n="$1" '
BEGIN {
sign = (n < 0 ? "-" : "")
if (n < 0)
n = -n
if (n >= 1000000000)
printf "%s%.2fG", sign, n/1000000000
else if (n >= 1000000)
printf "%s%.2fM", sign, n/1000000
else if (n >= 1000)
printf "%s%.2fk", sign, n/1000
else
printf "%s%.0f", sign, n
}
'
}
human_bytes() {
awk -v b="$1" '
BEGIN {
sign = (b < 0 ? "-" : "")
if (b < 0)
b = -b
if (b >= 1099511627776)
printf "%s%.2f TiB", sign, b/1099511627776
else if (b >= 1073741824)
printf "%s%.2f GiB", sign, b/1073741824
else if (b >= 1048576)
printf "%s%.2f MiB", sign, b/1048576
else if (b >= 1024)
printf "%s%.2f KiB", sign, b/1024
else
printf "%s%.0f B", sign, b
}
'
}
human_rate() {
local bytes="$1"
local secs="$2"
local rate
rate=$(
awk -v b="$bytes" -v s="$secs" '
BEGIN {
if (s <= 0)
print 0
else
printf "%.0f", b/s
}
'
)
printf '%s/s' "$(human_bytes "$rate")"
}
duration_fmt() {
local s="$1"
if (( s >= 86400 )); then
printf '%dd %02dh %02dm %02ds' \
$((s/86400)) \
$(((s%86400)/3600)) \
$(((s%3600)/60)) \
$((s%60))
elif (( s >= 3600 )); then
printf '%dh %02dm %02ds' \
$((s/3600)) \
$(((s%3600)/60)) \
$((s%60))
else
printf '%dm %02ds' \
$((s/60)) \
$((s%60))
fi
}
# =============================================================================
# CLASSIFICAÇÕES
# =============================================================================
classify_demand() {
local p="$1"
local samples="$2"
if (( samples < MIN_DEMAND_SAMPLES )); then
echo "AMOSTRA BAIXA"
return
fi
awk \
-v p="$p" \
-v e="$DD_EXCELLENT_MAX" \
-v g="$DD_GOOD_MAX" \
-v w="$DD_WARN_MAX" '
BEGIN {
if (p <= e)
print "EXCELENTE"
else if (p <= g)
print "BOM"
else if (p <= w)
print "ATENCAO"
else
print "RUIM"
}
'
}
classify_l2() {
local p="$1"
local samples="$2"
if (( samples < MIN_L2_SAMPLES )); then
echo "AMOSTRA BAIXA"
return
fi
awk \
-v p="$p" \
-v e="$L2_EXCELLENT_MIN" \
-v g="$L2_GOOD_MIN" \
-v w="$L2_WARN_MIN" '
BEGIN {
if (p >= e)
print "EXCELENTE"
else if (p >= g)
print "BOM"
else if (p >= w)
print "ATENCAO"
else
print "RUIM"
}
'
}
pollution_status() {
local mru="$1"
local l2hit="$2"
local samples="$3"
if (( samples < MIN_L2_SAMPLES )); then
echo "INCONCLUSIVO (amostra baixa)"
return
fi
awk \
-v m="$mru" \
-v h="$l2hit" \
-v warn="$MRU_WARN_MIN" \
-v bad="$MRU_BAD_MIN" \
-v low="$L2_LOW_FOR_POLLUTION" '
BEGIN {
if (m >= bad && h < low)
print "FORTE INDICIO"
else if (m >= warn && h < 25)
print "POSSIVEL"
else
print "NAO EVIDENTE"
}
'
}
# =============================================================================
# THRESHOLDS
# =============================================================================
print_thresholds() {
section "THRESHOLDS UTILIZADOS"
printf '%sDemand Data Miss%s\n' "$BOLD" "$RESET"
printf ' <= %2s%% ' "$DD_EXCELLENT_MAX"
status_color "EXCELENTE"
echo
printf ' <= %2s%% ' "$DD_GOOD_MAX"
status_color "BOM"
echo
printf ' <= %2s%% ' "$DD_WARN_MAX"
status_color "ATENCAO"
echo
printf ' > %2s%% ' "$DD_WARN_MAX"
status_color "RUIM"
echo
echo
printf '%sL2ARC Hit%s\n' "$BOLD" "$RESET"
printf ' >= %2s%% ' "$L2_EXCELLENT_MIN"
status_color "EXCELENTE"
echo
printf ' >= %2s%% ' "$L2_GOOD_MIN"
status_color "BOM"
echo
printf ' >= %2s%% ' "$L2_WARN_MIN"
status_color "ATENCAO"
echo
printf ' < %2s%% ' "$L2_WARN_MIN"
status_color "RUIM"
echo
echo
printf '%sAmostra mínima%s\n' "$BOLD" "$RESET"
printf ' Demand Data: %s acessos\n' "$MIN_DEMAND_SAMPLES"
printf ' L2ARC: %s consultas\n' "$MIN_L2_SAMPLES"
echo
printf '%sDemand Data tem prioridade sobre ARC Total e L2ARC.%s\n' \
"$YELLOW" "$RESET"
}
# =============================================================================
# GLOSSÁRIO / COMO INTERPRETAR
# =============================================================================
print_glossary() {
section "COMO INTERPRETAR ESTE RELATÓRIO"
printf '%sARC%s\n' "$BOLD$BRIGHT_CYAN" "$RESET"
echo " Cache principal do ZFS armazenado na RAM."
echo " É a camada de cache mais rápida."
echo
printf '%sL2ARC%s\n' "$BOLD$BRIGHT_CYAN" "$RESET"
echo " Segundo nível de cache, normalmente SSD/NVMe."
echo " É consultado quando o dado não está disponível no ARC."
echo
printf '%sHit%s\n' "$BOLD$GREEN" "$RESET"
echo " O dado solicitado foi encontrado naquela camada de cache."
echo " Em geral, quanto maior o percentual, melhor."
echo
printf '%sMiss%s\n' "$BOLD$YELLOW" "$RESET"
echo " O dado não estava naquela camada de cache."
echo " A leitura precisa seguir para outra camada."
echo
printf '%sDemand Data%s\n' "$BOLD$BRIGHT_CYAN" "$RESET"
echo " Dados pedidos diretamente pelas aplicações, VMs, NFS, iSCSI etc."
echo " É o indicador principal de performance deste relatório."
echo
printf '%sDemand Hit%s\n' "$BOLD$GREEN" "$RESET"
echo " A aplicação pediu um dado e ele foi encontrado no ARC."
echo
printf '%sDemand Miss%s\n' "$BOLD$YELLOW" "$RESET"
echo " A aplicação pediu um dado e ele não estava no ARC."
echo " Quanto menor esse percentual, melhor."
echo
printf '%sI/O Hit%s\n' "$BOLD$CYAN" "$RESET"
echo " A requisição foi atendida por um I/O já em andamento ou estrutura"
echo " equivalente, sem ser um hit tradicional do ARC."
echo
printf '%sARC Total%s\n' "$BOLD$BRIGHT_CYAN" "$RESET"
echo " Soma dados, metadata, prefetch e outros acessos."
echo " Serve como contexto, mas pode mascarar problemas porque metadata"
echo " normalmente possui hit rate muito alto."
echo
printf '%sMRU - Most Recently Used%s\n' "$BOLD$YELLOW" "$RESET"
echo " Dados usados recentemente."
echo " Muito MRU no L2ARC pode indicar dados de passagem ou pouca reutilização."
echo
printf '%sMFU - Most Frequently Used%s\n' "$BOLD$GREEN" "$RESET"
echo " Dados utilizados repetidamente."
echo " Normalmente são candidatos valiosos para permanecer no cache."
echo
printf '%sPrefetch%s\n' "$BOLD$CYAN" "$RESET"
echo " Dados lidos antecipadamente pelo ZFS porque ele prevê que serão usados."
echo
printf '%sL2ARC Hit Ratio%s\n' "$BOLD$GREEN" "$RESET"
echo " Percentual das consultas ao L2ARC que encontraram o dado no SSD."
echo
printf '%sL2ARC Writes%s\n' "$BOLD$CYAN" "$RESET"
echo " Quantidade de dados enviada ao dispositivo de L2ARC durante a janela."
echo
printf '%sLogical Size%s\n' "$BOLD$CYAN" "$RESET"
echo " Quantidade lógica de dados representada pelo L2ARC."
echo
printf '%sAllocated Size / ASIZE%s\n' "$BOLD$CYAN" "$RESET"
echo " Quantidade efetivamente alocada no dispositivo de L2ARC."
echo
printf '%sLow-memory abort%s\n' "$BOLD$BRIGHT_RED" "$RESET"
echo " O ZFS abortou alimentação do L2ARC devido a pressão de memória."
echo " O ideal é que esse contador NÃO aumente durante a medição."
echo
printf '%sChurn%s\n' "$BOLD$YELLOW" "$RESET"
echo " Dados entram e saem rapidamente do cache sem reutilização suficiente."
echo
printf '%sPoluição de cache%s\n' "$BOLD$YELLOW" "$RESET"
echo " Dados pouco úteis ocupam o cache e podem expulsar dados mais valiosos."
echo " MRU muito alto + L2ARC hit baixo pode ser um indício."
echo
printf '%sAmostra%s\n' "$BOLD$BRIGHT_BLUE" "$RESET"
echo " Quantidade de operações observadas na janela."
echo " Percentuais obtidos com poucas operações podem não ser representativos."
echo
printf '%sThreshold%s\n' "$BOLD$BRIGHT_BLUE" "$RESET"
echo " Faixa usada pelo script para classificar uma métrica."
echo " São referências heurísticas, não limites absolutos do OpenZFS."
echo
printf '%sCAMINHO SIMPLIFICADO DE UMA LEITURA%s\n' \
"$BOLD$BRIGHT_CYAN" "$RESET"
echo
echo " Aplicação / VM"
echo " |"
echo " v"
echo " [ ARC ] RAM"
echo " |"
echo " MISS"
echo " |"
echo " v"
echo " [ L2ARC ] SSD/NVMe"
echo " |"
echo " MISS"
echo " |"
echo " v"
echo " [ ZFS POOL ] HDD / RAIDZ"
echo
printf '%sORDEM RECOMENDADA DE LEITURA%s\n' \
"$BOLD$BRIGHT_CYAN" "$RESET"
echo
echo " 1. Demand Data Miss"
echo " -> Está escapando muita leitura do ARC?"
echo
echo " 2. Low-memory aborts"
echo " -> Há pressão de memória afetando o L2ARC?"
echo
echo " 3. L2ARC Hit"
echo " -> Quando o ARC falha, o SSD está ajudando?"
echo
echo " 4. MRU x MFU"
echo " -> O cache contém dados reutilizados ou dados de passagem?"
echo
echo " 5. L2ARC Writes"
echo " -> Estamos escrevendo muito no SSD para pouco benefício?"
echo
echo " 6. ARC Total"
echo " -> Use apenas como visão geral."
echo
printf '%sREGRA PRÁTICA%s\n' "$BOLD$BRIGHT_GREEN" "$RESET"
echo
echo " Demand Miss baixo + L2ARC Hit baixo"
echo " pode ser perfeitamente normal:"
echo
echo " o ARC já está atendendo quase toda a carga."
echo
printf '%sSINAL DE ATENÇÃO%s\n' "$BOLD$BRIGHT_YELLOW" "$RESET"
echo
echo " Demand Miss alto"
echo " + L2ARC Hit baixo"
echo " + MRU muito alto"
echo " + muitos writes no L2ARC"
echo
echo " pode indicar baixa eficiência ou poluição do L2ARC."
}
# =============================================================================
# HELP
# =============================================================================
show_help() {
echo
line
printf '%s%s ARC / L2ARC MONITOR%s\n' \
"$BOLD" "$BRIGHT_CYAN" "$RESET"
line
cat <<EOF
Uso:
/root/arc-monitor.sh start
Inicia ou reinicia uma janela de medição.
/root/arc-monitor.sh report
Mostra o relatório desde o último start.
/root/arc-monitor.sh thresholds
Mostra os thresholds utilizados.
/root/arc-monitor.sh glossary
Explica ARC, L2ARC, MRU, MFU, hit, miss etc.
Exemplo:
/root/arc-monitor.sh start
# Deixe o storage trabalhar normalmente por 30-60 minutos.
/root/arc-monitor.sh report
IMPORTANTE:
O script NÃO gera carga no pool e NÃO altera configurações do ZFS.
EOF
line
}
# =============================================================================
# EXECUÇÃO
# =============================================================================
case "${1:-help}" in
# -----------------------------------------------------------------------------
# START
# -----------------------------------------------------------------------------
start|reset)
if [[ ! -r "$STATS" ]]; then
printf '%sERRO:%s não consigo ler %s\n' \
"$BRIGHT_RED" "$RESET" "$STATS"
exit 1
fi
snapshot > "$STATE"
echo
line
printf '%s%s ARC/L2ARC - MEDIÇÃO INICIADA%s\n' \
"$BOLD" "$BRIGHT_CYAN" "$RESET"
line
printf '%-24s %s\n' \
"Host:" \
"$(value "$STATE" host)"
printf '%-24s %s\n' \
"Início:" \
"$(value "$STATE" date)"
printf '%-24s %s\n' \
"Snapshot:" \
"$STATE"
echo
printf '%sDeixe o storage operar normalmente.%s\n' \
"$GREEN" "$RESET"
echo
echo "Depois execute:"
echo
printf ' %s/root/arc-monitor.sh report%s\n' \
"$BOLD$BRIGHT_GREEN" "$RESET"
echo
printf '%sO report pode ser executado várias vezes sem perder o início.%s\n' \
"$DIM" "$RESET"
echo
line
;;
# -----------------------------------------------------------------------------
# REPORT
# -----------------------------------------------------------------------------
report)
if [[ ! -f "$STATE" ]]; then
printf '%sERRO:%s não existe snapshot inicial.\n' \
"$BRIGHT_RED" "$RESET"
echo
echo "Execute:"
echo
echo " /root/arc-monitor.sh start"
exit 1
fi
CURRENT=$(mktemp)
trap 'rm -f "$CURRENT"' EXIT
snapshot > "$CURRENT"
B_TS=$(num_or_zero "$(value "$STATE" timestamp)")
A_TS=$(num_or_zero "$(value "$CURRENT" timestamp)")
SECS=$((A_TS - B_TS))
if (( SECS <= 0 )); then
echo "ERRO: intervalo inválido."
exit 1
fi
# =========================================================================
# ARC TOTAL
# =========================================================================
HITS=$(delta hits)
IOHITS=$(delta iohits)
MISSES=$(delta misses)
TOTAL=$((HITS + IOHITS + MISSES))
ARC_HIT_P=$(pct_num "$HITS" "$TOTAL")
ARC_IO_P=$(pct_num "$IOHITS" "$TOTAL")
ARC_MISS_P=$(pct_num "$MISSES" "$TOTAL")
# =========================================================================
# DEMAND DATA
# =========================================================================
DD_HITS=$(delta demand_data_hits)
DD_IOHITS=$(delta demand_data_iohits)
DD_MISSES=$(delta demand_data_misses)
DD_TOTAL=$((DD_HITS + DD_IOHITS + DD_MISSES))
DD_HIT_P=$(pct_num "$DD_HITS" "$DD_TOTAL")
DD_IO_P=$(pct_num "$DD_IOHITS" "$DD_TOTAL")
DD_MISS_P=$(pct_num "$DD_MISSES" "$DD_TOTAL")
# =========================================================================
# L2ARC
# =========================================================================
L2_HITS=$(delta l2_hits)
L2_MISSES=$(delta l2_misses)
L2_TOTAL=$((L2_HITS + L2_MISSES))
L2_HIT_P=$(pct_num "$L2_HITS" "$L2_TOTAL")
L2_MISS_P=$(pct_num "$L2_MISSES" "$L2_TOTAL")
L2_WRITES=$(delta l2_write_bytes)
L2_LOWMEM=$(delta l2_abort_lowmem)
L2_SIZE_BEFORE=$(num_or_zero "$(value "$STATE" l2_size)")
L2_SIZE_NOW=$(num_or_zero "$(value "$CURRENT" l2_size)")
L2_ASIZE_BEFORE=$(num_or_zero "$(value "$STATE" l2_asize)")
L2_ASIZE_NOW=$(num_or_zero "$(value "$CURRENT" l2_asize)")
L2_SIZE_DELTA=$((L2_SIZE_NOW - L2_SIZE_BEFORE))
L2_ASIZE_DELTA=$((L2_ASIZE_NOW - L2_ASIZE_BEFORE))
L2_MRU=$(num_or_zero "$(value "$CURRENT" l2_mru_asize)")
L2_MFU=$(num_or_zero "$(value "$CURRENT" l2_mfu_asize)")
L2_PREFETCH=$(num_or_zero "$(value "$CURRENT" l2_prefetch_asize)")
L2_MRU_P=$(pct_num "$L2_MRU" "$L2_ASIZE_NOW")
L2_MFU_P=$(pct_num "$L2_MFU" "$L2_ASIZE_NOW")
L2_PREFETCH_P=$(pct_num "$L2_PREFETCH" "$L2_ASIZE_NOW")
# =========================================================================
# MEMÓRIA
# =========================================================================
MEM_NOW=$(num_or_zero "$(value "$CURRENT" mem_available)")
ARC_SIZE_NOW=$(num_or_zero "$(value "$CURRENT" size)")
ARC_CMAX_NOW=$(num_or_zero "$(value "$CURRENT" c_max)")
# =========================================================================
# CLASSIFICAÇÕES
# =========================================================================
DD_STATUS=$(classify_demand "$DD_MISS_P" "$DD_TOTAL")
L2_STATUS=$(classify_l2 "$L2_HIT_P" "$L2_TOTAL")
POLLUTION=$(
pollution_status \
"$L2_MRU_P" \
"$L2_HIT_P" \
"$L2_TOTAL"
)
# =========================================================================
# RESULTADO GERAL
# =========================================================================
if (( L2_LOWMEM > 0 )); then
OVERALL="RUIM - houve low-memory abort"
elif [[ "$DD_STATUS" == "RUIM" ]]; then
OVERALL="RUIM - demand miss alto"
elif [[ "$DD_STATUS" == "ATENCAO" ]]; then
OVERALL="ATENCAO - demand miss acima do desejável"
elif [[ "$DD_STATUS" == "AMOSTRA BAIXA" ]]; then
OVERALL="INCONCLUSIVO - pouca amostra de Demand Data"
elif [[ "$DD_STATUS" == "EXCELENTE" ]]; then
OVERALL="EXCELENTE - ARC atendendo muito bem a carga atual"
else
OVERALL="BOM - ARC atendendo bem a carga atual"
fi
# =========================================================================
# CABEÇALHO
# =========================================================================
echo
line
printf '%s%s ARC / L2ARC - RELATÓRIO DA JANELA%s\n' \
"$BOLD" "$BRIGHT_CYAN" "$RESET"
line
printf '%-25s %s\n' \
"Host:" \
"$(value "$CURRENT" host)"
printf '%-25s %s\n' \
"Início:" \
"$(value "$STATE" date)"
printf '%-25s %s\n' \
"Fim:" \
"$(value "$CURRENT" date)"
printf '%-25s %s\n' \
"Duração:" \
"$(duration_fmt "$SECS")"
echo
printf '%s%-25s%s ' \
"$BOLD" \
"RESULTADO GERAL:" \
"$RESET"
status_color "$OVERALL"
echo
# =========================================================================
# DEMAND DATA
# =========================================================================
section "DEMAND DATA - INDICADOR PRINCIPAL DE PERFORMANCE"
printf '%-25s %12s %12s\n' \
"Métrica" \
"Quantidade" \
"Percentual"
printf '%-25s %12s %12s\n' \
"Demand hits" \
"$(human_count "$DD_HITS")" \
"$(pct_fmt "$DD_HIT_P")"
printf '%-25s %12s %12s\n' \
"Demand I/O hits" \
"$(human_count "$DD_IOHITS")" \
"$(pct_fmt "$DD_IO_P")"
printf '%-25s %12s %12s\n' \
"Demand misses" \
"$(human_count "$DD_MISSES")" \
"$(pct_fmt "$DD_MISS_P")"
printf '%-25s %12s\n' \
"Amostra" \
"$(human_count "$DD_TOTAL")"
echo
printf '%-25s ' "Status Demand:"
status_color "$DD_STATUS"
echo
# =========================================================================
# ARC TOTAL
# =========================================================================
section "ARC TOTAL - CONTEXTO SECUNDÁRIO"
printf '%-25s %12s %12s\n' \
"Métrica" \
"Quantidade" \
"Percentual"
printf '%-25s %12s %12s\n' \
"ARC hits" \
"$(human_count "$HITS")" \
"$(pct_fmt "$ARC_HIT_P")"
printf '%-25s %12s %12s\n' \
"ARC I/O hits" \
"$(human_count "$IOHITS")" \
"$(pct_fmt "$ARC_IO_P")"
printf '%-25s %12s %12s\n' \
"ARC misses" \
"$(human_count "$MISSES")" \
"$(pct_fmt "$ARC_MISS_P")"
# =========================================================================
# L2ARC
# =========================================================================
section "L2ARC - EFICIÊNCIA NA JANELA"
printf '%-25s %12s %12s\n' \
"Métrica" \
"Quantidade" \
"Percentual"
printf '%-25s %12s %12s\n' \
"L2ARC hits" \
"$(human_count "$L2_HITS")" \
"$(pct_fmt "$L2_HIT_P")"
printf '%-25s %12s %12s\n' \
"L2ARC misses" \
"$(human_count "$L2_MISSES")" \
"$(pct_fmt "$L2_MISS_P")"
printf '%-25s %12s\n' \
"Consultas L2ARC" \
"$(human_count "$L2_TOTAL")"
echo
printf '%-25s ' "Status L2ARC:"
status_color "$L2_STATUS"
echo
if (( L2_TOTAL < MIN_L2_SAMPLES )); then
echo
printf '%sOBSERVAÇÃO:%s\n' \
"$BRIGHT_BLUE" "$RESET"
echo " Poucas consultas ao L2ARC nesta janela."
echo " Não use este hit ratio isoladamente para decidir tuning."
fi
# =========================================================================
# PERFIL L2ARC
# =========================================================================
section "L2ARC - ATIVIDADE / PERFIL"
printf '%-31s %s\n' \
"Escrito na janela:" \
"$(human_bytes "$L2_WRITES")"
printf '%-31s %s\n' \
"Taxa média de escrita:" \
"$(human_rate "$L2_WRITES" "$SECS")"
printf '%-31s %s\n' \
"Variação logical size:" \
"$(human_bytes "$L2_SIZE_DELTA")"
printf '%-31s %s\n' \
"Variação allocated size:" \
"$(human_bytes "$L2_ASIZE_DELTA")"
printf '%-31s %s\n' \
"L2ARC logical size atual:" \
"$(human_bytes "$L2_SIZE_NOW")"
printf '%-31s %s\n' \
"L2ARC allocated atual:" \
"$(human_bytes "$L2_ASIZE_NOW")"
echo
printf '%-31s %s (%s)\n' \
"MRU atual:" \
"$(human_bytes "$L2_MRU")" \
"$(pct_fmt "$L2_MRU_P")"
printf '%-31s %s (%s)\n' \
"MFU atual:" \
"$(human_bytes "$L2_MFU")" \
"$(pct_fmt "$L2_MFU_P")"
printf '%-31s %s (%s)\n' \
"Prefetch atual:" \
"$(human_bytes "$L2_PREFETCH")" \
"$(pct_fmt "$L2_PREFETCH_P")"
echo
printf '%-31s ' "Indício de poluição/churn:"
status_color "$POLLUTION"
echo
# =========================================================================
# MEMÓRIA
# =========================================================================
section "MEMÓRIA / ARC"
printf '%-31s %s\n' \
"ARC atual:" \
"$(human_bytes "$ARC_SIZE_NOW")"
printf '%-31s %s\n' \
"ARC máximo:" \
"$(human_bytes "$ARC_CMAX_NOW")"
printf '%-31s %s\n' \
"MemAvailable Linux:" \
"$(human_bytes "$MEM_NOW")"
printf '%-31s ' \
"Novos low-memory aborts:"
if (( L2_LOWMEM == 0 )); then
printf '%s0 [OK]%s\n' \
"$GREEN" "$RESET"
else
printf '%s%s [RUIM]%s\n' \
"$BRIGHT_RED" \
"$L2_LOWMEM" \
"$RESET"
fi
# =========================================================================
# DOCUMENTAÇÃO NO PRÓPRIO RELATÓRIO
# =========================================================================
print_thresholds
print_glossary
echo
line
;;
# -----------------------------------------------------------------------------
# THRESHOLDS
# -----------------------------------------------------------------------------
thresholds)
print_thresholds
;;
# -----------------------------------------------------------------------------
# GLOSSARY
# -----------------------------------------------------------------------------
glossary)
print_glossary
;;
# -----------------------------------------------------------------------------
# HELP
# -----------------------------------------------------------------------------
help|-h|--help)
show_help
;;
# -----------------------------------------------------------------------------
# INVALID
# -----------------------------------------------------------------------------
*)
echo "Comando inválido: $1"
show_help
exit 1
;;
esac
EOF
chmod 700 /root/arc-monitor.shPROPÓSITO
Medir a eficiência do cache durante uma janela real de utilização, comparando os contadores do kernel entre dois momentos.
Quando usar: Quando os números acumulados desde o boot já não representam a carga atual e é preciso medir um período específico.
Pré-requisitos: TrueNAS SCALE ou OpenZFS. O script apenas lê contadores: não gera carga no pool nem altera parâmetros.
