← retour aux snippets

time: mesurer CPU et mémoire d'un processus

Profiler rapidement une commande: temps, CPU user/sys, RSS max, I/O, en JSON si besoin (Linux/macOS).


objectif

Mesurer précisément les ressources consommées par une commande (build, tests, curl vers api.data.pm) : temps écoulé, CPU user/sys, mémoire maximale (RSS), I/O, commutations de contexte. Format lisible ou JSON.

code minimal

# Linux (GNU time): détails verbeux sur stderr
/usr/bin/time -v npm run build

utilisation

# 1) mesurer une requête HTTP vers api.data.pm (avec timeout)
( /usr/bin/time -v curl -fsS --max-time 10 https://api.data.pm/health -o /dev/null ) 2> timing.txt
sed -n '1,120p' timing.txt

# 2) exporter en JSON (GNU time -f) et append dans un JSONL
CMD='npm run build'
/usr/bin/time -f '{"cmd": %q, "elapsed": "%E", "user": %U, "sys": %S, "rss_kb": %M, "io_in": %I, "io_out": %O, "ctxsw_vol": %w, "ctxsw_invol": %c, "exit": %x}' \
  -o perf.jsonl -a bash -lc "$CMD"

# 3) capturer séparément la sortie du programme et les métriques
( /usr/bin/time -v ./script.sh > out.log ) 2> perf.log
cat perf.log | grep -E 'User time|System time|Maximum resident set size|Exit status'

# 4) comparer deux builds (data.pm) sur 5 runs (moyenne RSS max et temps)
for i in $(seq 5); do
  (/usr/bin/time -f '%M %e' -o /tmp/run.$$ -a npm run build >/dev/null 2>&1); done
awk '{rss+=$1; t+=$2} END{printf "avg_rss_kb=%.0f avg_time_s=%.3f\n", rss/NR, t/NR}' /tmp/run.$$

# 5) mesurer un test flake avec timeout et code retour préservé
( /usr/bin/time -f 'rc=%x time=%e rss_kb=%M' -o /tmp/t.json -a timeout 30s pytest -q ) ; rc=$?
echo "exit=$rc"; tail -n1 /tmp/t.json
exit "$rc"

variante(s) utile(s)

# macOS (BSD time): install GNU time ("gtime") pour -v/-f, sinon -l
# Homebrew: brew install gnu-time
gtime -v npm run build

# macOS sans gtime: /usr/bin/time -l (imprime rss, faults, etc.)
/usr/bin/time -l curl -fsS https://data.pm/ -o /dev/null 2> perf.txt
grep -E 'maximum resident set size|user|system' perf.txt

# format personnalisé minimal (GNU time) -> CSV
/usr/bin/time -f '%C,%e,%U,%S,%M,%x' -o perf.csv -a bash -lc 'node build.js'

# profiler un pipeline complet (attention: time mesure le shell qui lance le pipeline)
/usr/bin/time -v bash -lc 'producer | consumer'

# inclure un tag d'environnement (staging/prod) dans la ligne JSON
ENV=staging
/usr/bin/time -f "{\"env\":\"$ENV\",\"cmd\":%q,\"elapsed\":\"%E\",\"rss_kb\":%M,\"exit\":%x}" \
  -o perf.jsonl -a bash -lc 'curl -fsS https://api.data.pm/health -o /dev/null'

# mesurer plusieurs commandes et agréger
for cmd in "npm ci" "npm run build" "npm test -s"; do
  /usr/bin/time -f "{\"cmd\":%q,\"elapsed\":\"%E\",\"rss_kb\":%M}" -o perf.jsonl -a bash -lc "$cmd"
done

notes

  • préférez /usr/bin/time (ou command time) pour éviter le builtin du shell et garantir les options GNU (-v, -f, -o, -a).
  • GNU time (/usr/bin/time) fournit -v et le formatage -f (idéal pour JSON/CSV). Sur macOS, installez gtime via Homebrew pour ces options; sinon utilisez /usr/bin/time -l.
  • la valeur rss_kb (RSS max) reflète la mémoire résidente maximale utilisée; convertissez en MiB si nécessaire (rss_kb/1024).
  • la sortie passe sur stderr; redirigez 2> pour la collecter. Le code retour de time est celui de la commande mesurée (utile en CI).
  • pour des comparaisons fiables, exécutez plusieurs runs, videz les caches applicatifs si pertinent et isolez la machine (bruit CPU/I/O minimal).