Desempenho do Linux para jogos e workloads pesados: o que eu ajusto antes de culpar o hardware
Na semana passada, eu estava com um desktop rodando Arch Linux em cima de um Ryzen 7 e um SSD NVMe, e o problema não era falta de CPU nem de GPU. O gargalo aparecia quando eu alternava entre um jogo pesado em Proton e uma build grande de container. O sistema engasgava por causa de latência de I/O, scheduler mal ajustado e um desktop compositor metendo o dedo onde não devia. É exatamente aí que o desempenho do Linux deixa de ser teoria e vira engenharia de sistema. O desempenho do Linux melhora quando você para de tratar a máquina como “PC de uso geral” e começa a encará-la como um conjunto de filas, limites, prioridades e caches que precisam ser alinhados ao seu workload.
Quem trabalha com DevOps ou administração Linux já viu esse filme: um kernel excelente, pacotes bem mantidos, mas configuração padrão pensada para equilíbrio, não para resposta agressiva em jogos e aplicações pesadas. E equilíbrio, nesse contexto, é sinônimo de deixar performance na mesa. O que segue é o tipo de ajuste que eu faria num desktop de produção local, numa máquina de desenvolvimento com containers e, em vários pontos, num setup de gaming Linux sem firula.
Por que o Linux fica “pesado” mesmo com hardware forte?
Porque o problema quase nunca é um único componente. O CPU até sobra, mas a pilha inteira precisa cooperar: scheduler, governor de frequência, compositor gráfico, driver de GPU, cache de disco, I/O scheduler, swap, pressão de memória, isolamento de CPU e serviços de fundo. Se um elo começa a disputar tempo de CPU ou acesso ao NVMe em momentos errados, você sente stutter, frame pacing ruim, compilações lentas e desktop travado ao mesmo tempo.
Em jogos, o que mais aparece é latência irregular. Em aplicações pesadas, o vilão costuma ser I/O e memória. E há um erro clássico: tentar resolver tudo com um “kernel de baixa latência” ou com um pacote milagroso. Não é assim. O ganho real vem de encaixar cada camada no perfil da carga.
Quais métricas eu olho antes de mexer em qualquer coisa?
Eu começo pelo básico instrumentado. Sem isso, qualquer tweak vira religião. Rode estes comandos durante a carga real, não em repouso:
# CPU, run queue, contexto e uso por núcleo
mpstat -P ALL 1
# I/O, latência e saturação de disco
iostat -xz 1
# memória, swap e pressão
vmstat 1
# topologia de processos e threads
pidstat -t -u -d 1
# pressão de CPU, memória e I/O no cgroup raiz
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/io
Se você quer aprofundar, use perf e não chute. Um perfil simples já entrega muita coisa:
sudo perf top
sudo perf record -F 99 -g -- sleep 30
sudo perf report
Quando o frame time está ruim, eu olho também se há interrupções excessivas em um único núcleo:
watch -n1 'cat /proc/interrupts | sed -n "1,15p"'
Se o sistema está distribuindo IRQ de forma boba, o problema aparece rápido.
Kernel desktop ou kernel low-latency: qual eu uso para jogos?
Eu não tenho apego dogmático ao “low-latency” para gaming. Em muita máquina moderna, um kernel mainline bem configurado já entrega o que precisa. O que importa é se o kernel está compilado com as opções certas, se a distribuição aplica patches úteis e se o scheduler está coerente com o hardware.
Para jogos e desktop responsivo, faz sentido testar kernels com foco em latência e responsividade, mas sem esquecer que a maior diferença vem de configuração externa. Em desktops Linux, o benefício do low-latency costuma ser perceptível quando há carga mista: jogo + navegador com muitas abas + Discord/voz + gravação + uma build rodando em paralelo. Se a máquina é dedicada a jogos, eu priorizo:
- preempção mais agressiva;
- governor de CPU em modo performance ou schedutil bem calibrado;
- redução de ruído de serviços em segundo plano;
- GPU driver correto, com sincronização de frames funcionando.
Para checar o tipo de kernel e parâmetros de boot, eu uso:
uname -a
cat /proc/cmdline
sysctl kernel.sched_autogroup_enabled
sysctl kernel.sched_migration_cost_ns
Essa última linha não é enfeite. Em cargas interativas, sched_migration_cost_ns e afinidade de threads influenciam como o sistema espalha trabalho entre núcleos. E isso conversa diretamente com jogos e workloads pesados.
Como eu ajusto CPU governor, turbo e escalonamento sem quebrar estabilidade?
Governador errado é desperdício clássico. Em muitos notebooks e desktops, o default vem em powersave ou com política conservadora demais. Para jogo e build pesada, eu prefiro partir para performance em máquinas dedicadas, ou usar schedutil com driver P-state moderno e verificações de temperatura.
# Ver governadores disponíveis
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
# Ver estado atual
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
# Ajustar temporariamente para performance
sudo cpupower frequency-set -g performance
# Ver frequência atual por núcleo
watch -n1 "grep -m1 'cpu MHz' /proc/cpuinfo && cpupower frequency-info | sed -n '1,12p'"
Se você usa AMD, vale conferir o driver amd_pstate. Em várias máquinas Ryzen recentes, ele traz comportamento melhor do que o antigo arranjo genérico. Para verificar:
cat /sys/devices/system/cpu/amd_pstate/status 2>/dev/null
cat /sys/devices/system/cpu/intel_pstate/status 2>/dev/null
Eu também olho o boost térmico. Não adianta travar tudo em performance se o cooler vive no limite e o chip entra em throttling. Faça um stress curto e observe:
sudo apt install -y stress-ng lm-sensors 2>/dev/null || true
sensors
stress-ng --cpu 8 --vm 2 --vm-bytes 70% --timeout 60s
Se a temperatura dispara e o clock cai, o ganho teórico do governor some. Aqui o trabalho é físico: curva de fan, pasta térmica, airflow e limite de potência da placa-mãe entram na jogada.
O que fazer com RAM, swap e zram quando o jogo e o build brigam pela memória?
Esse é um ponto que muita gente ignora até o desktop congelar. Em Linux, swap não é só “memória de emergência”; ela também ajuda a suavizar picos. O problema é usar swap em SSD sem entender a latência percebida. Para desktop com cargas mistas, eu gosto de zram bem dimensionado e swap tradicional como retaguarda, não como linha de frente.
Primeiro: veja a pressão de memória e o comportamento atual:
free -h
swapon --show
cat /proc/pressure/memory
vmstat 1
Se houver swapping agressivo durante a sessão de jogo, você precisa agir. Uma configuração de zram em systemd pode ficar assim:
# /etc/systemd/zram-generator.conf
[zram0]
zram-size = ram / 2
compression-algorithm = zstd
swap-priority = 100
Isso não é receita universal. Em máquinas com 32 GB ou 64 GB, metade da RAM em zram é conservador; em notebooks com 16 GB, eu já prefiro algo mais enxuto. O ponto é reduzir o impacto de páginas frias e manter responsividade quando um jogo e um navegador resolvem disputar recursos.
Se você quer aliviar comportamento de swap sem cair no extremo, mexa no vm.swappiness com parcimônia:
sudo tee /etc/sysctl.d/99-desktop-performance.conf >/dev/null <<'EOF'
vm.swappiness=10
vm.vfs_cache_pressure=50
vm.dirty_background_ratio=5
vm.dirty_ratio=15
EOF
sudo sysctl --system
Eu prefiro dirty_ratio e dirty_background_ratio controlados porque builds e jogos gravando shader cache ou logs em paralelo podem gerar picos de escrita. Sem isso, o flush vem como pancada.
Como eu reduzo stutter gráfico no compositor e no driver de GPU?
Sem uma cadeia gráfica limpa, todo o resto perde valor. O compositor do desktop pode ser o maior gerador de stutter, principalmente em X11 mal configurado ou Wayland com driver quebrado. Em máquina de gaming Linux, eu quero três coisas: driver estável, vsync bem definido e minimização de cópias desnecessárias.
Para verificar o stack gráfico, eu sempre confiro:
glxinfo -B 2>/dev/null | sed -n '1,20p'
vulkaninfo --summary 2>/dev/null | sed -n '1,40p'
lsmod | egrep 'amdgpu|nouveau|nvidia|i915'
Se o cenário for Wayland, a sessão pode ser excelente. Se for X11, eu costumo desativar o compositor durante jogos pesados, ou usar uma configuração que permita “unredirect fullscreen windows”. Isso depende do ambiente, mas a lógica é simples: evitar que o compositor reconstrua frames sem necessidade.
Em setups com Proton e Vulkan, a pré-compilação de shaders e o cache ajudam bastante. Não é glamour. É menos compilação no meio da partida. Mantenha o cache em SSD rápido e com espaço livre de sobra. Se o disco fica cheio, a latência sobe.
Quais serviços eu desativo em um desktop dedicado a jogos e render/compile?
Eu não saio desligando tudo por esporte. Mas um desktop de alto desempenho não precisa carregar daemon de impressora, descoberta de Bluetooth quando não há uso, indexadores e serviços que acordam CPU sem entregar valor naquele momento. Em uma estação focada em jogos e compilação, eu faço inventário e corto o que não agrega.
Liste o que está ativo:
systemctl --type=service --state=running
systemctl --type=timer
Exemplos que eu reviso com frequência:
sudo systemctl disable --now cups.service
sudo systemctl disable --now avahi-daemon.service
sudo systemctl disable --now bluetooth.service
Mas isso depende do seu hardware e do uso real. Notebook corporativo e desktop gamer não recebem o mesmo tratamento. O critério é simples: se o serviço não entra na sessão de uso, ele não merece acordar CPU no meio da carga.
Automação com Ansible para um baseline repetível
Eu gosto de deixar o baseline versionado. Se você monta várias máquinas, Ansible é a forma limpa de manter a mesma postura de performance. Um playbook enxuto já resolve muito:
---
- name: Baseline de desempenho para desktop Linux
hosts: workstations
become: true
tasks:
- name: Instalar pacotes úteis
package:
name:
- cpupower
- lm_sensors
- tuned
- iotop
- sysstat
state: present
- name: Aplicar sysctl de desktop
copy:
dest: /etc/sysctl.d/99-desktop-performance.conf
content: |
vm.swappiness=10
vm.vfs_cache_pressure=50
vm.dirty_background_ratio=5
vm.dirty_ratio=15
notify: reload sysctl
- name: Desabilitar serviços não usados
systemd:
name: "{{ item }}"
enabled: false
state: stopped
loop:
- cups.service
- avahi-daemon.service
ignore_errors: true
handlers:
- name: reload sysctl
command: sysctl --system
Isso é melhor do que anotar tweeks num bloco de notas e repetir manualmente. Automação evita drift.
Como otimizar I/O para builds, containers e shader cache?
Para cargas pesadas, o disco costuma ser o gargalo silencioso. NVMe moderno ajuda, mas não faz milagre se o filesystem, o mount option e a fila estiverem mal ajustados. Eu observo latência com iostat -xz e procuro sinais como await alto, %util colado em 100% e r/s com fila crescente.
Se o disco é SSD/NVMe, algumas decisões práticas fazem diferença:
- usar
noatimenos sistemas de arquivos; - evitar encher o SSD além de 80% em uso constante;
- deixar cache e build artifacts em partição rápida;
- manter TRIM habilitado com timer periódico.
Exemplo de /etc/fstab com noatime:
UUID=xxxx-xxxx / ext4 defaults,noatime,commit=60 0 1
UUID=yyyy-yyyy /home ext4 defaults,noatime,commit=60 0 2
O commit=60 reduz frequência de flush de metadados. Em desktop isso costuma funcionar bem. Em workstation com escrita intensa e tolerância menor a perda de dados, eu revisaria esse valor com cuidado. Nada aqui é mágico.
Para TRIM periódico:
sudo systemctl enable --now fstrim.timer
systemctl status fstrim.timer
Se você usa Docker ou Podman para builds e testes, o storage driver importa. OverlayFS mal posicionado em disco lento transforma o ambiente em peneira. Em máquinas de desenvolvimento, eu costumo manter imagens e volumes em SSD separado, quando existe espaço físico para isso.
Qual configuração de containers ajuda sem sabotar o desktop?
Containers competem por CPU, memória e I/O com o que está na sua sessão gráfica. Se você roda compilações pesadas em Docker e ainda joga, coloque limites. Sem isso, o kernel faz o trabalho dele, mas você não vai gostar da forma como ele distribui sofrimento.
Um exemplo de docker-compose.yml com limites de recursos:
version: "3.9"
services:
buildbox:
image: debian:stable-slim
command: sleep infinity
deploy:
resources:
limits:
cpus: '4.0'
memory: 8G
reservations:
memory: 2G
ulimits:
nofile:
soft: 1048576
hard: 1048576
volumes:
- ./src:/src
- ./cache:/cache
No Docker local, deploy nem sempre é honrado fora do Swarm. Então eu também ajusto na linha de comando:
docker run --rm -it
--cpus=4
--memory=8g
--memory-swap=8g
--ulimit nofile=1048576:1048576
-v "$PWD/src:/src"
debian:stable-slim bash
Para workloads realmente pesados, eu prefiro isolar por cgroup e usar systemd-run:
sudo systemd-run --scope -p CPUQuota=400% -p MemoryMax=8G -p IOWeight=100 make -j8
Isso é prático e previsível. Melhor que confiar que a sessão do desktop vai se defender sozinha.
Como usar cgroups e systemd para priorizar o jogo sem matar minhas builds?
Eu gosto de separar a carga interativa da carga batch. Se o jogo está rodando, o sistema deve tratar essa sessão com prioridade para latência; se a build está rodando, ela precisa aceitar que o desktop existe. O caminho mais limpo em desktops Linux modernos é usar systemd e cgroups v2 para limitar e priorizar.
Exemplo de unidade de serviço para um runner pesado com prioridade menor:
# /etc/systemd/system/batch-build.service
[Unit]
Description=Build batch com prioridade reduzida
[Service]
Type=simple
ExecStart=/usr/bin/make -C /home/dev/project -j8
Nice=10
CPUWeight=50
IOWeight=50
MemoryMax=12G
TasksMax=512
Para tarefas interativas, eu inverto a lógica com peso maior e menor niceness. O segredo não é “tunar tudo para 11”. É distribuir o orçamento de forma declarada.
Verifique se o sistema está em cgroups v2:
stat -fc %T /sys/fs/cgroup
Se retornar cgroup2fs, ótimo. A modelagem fica muito mais coerente.
Quais ajustes eu faria em um notebook Linux para jogos e trabalho pesado?
Notebook é outro jogo. Bateria, temperatura e limitação térmica são os três freios principais. Eu começo pelo perfil energético e pelos estados de suspensão da GPU, porque muita máquina portátil perde desempenho em nome de economia mesmo ligada na tomada.
Para monitorar consumo e estados de energia:
powertop
upower -i $(upower -e | grep BAT)
cat /sys/class/drm/card0/device/power_dpm_state 2>/dev/null
Se o hardware permite, mantenha o modo de energia agressivo quando conectado à fonte. Em muitos desktops móveis, vale revisar o perfil do gerenciador de energia e desativar economia excessiva durante sessões pesadas. O ganho de estabilidade térmica compensa.
Também reviso a GPU híbrida. Em notebooks com iGPU + dGPU, enviar o jogo para a GPU errada ou manter a dedicada desperta sem uso destrói autonomia e aquece o chassi. O ambiente gráfico deve iniciar o aplicativo certo no hardware certo. Em Linux isso exige conferir variáveis, offloading e suporte do compositor. Não existe atalho universal.
Quais sinais mostram que o gargalo não é mais o Linux e sim o hardware?
Quando você já ajustou governor, compositor, cgroups, swap, I/O e serviços, o que sobra é aquilo que não dá para mascarar. RAM insuficiente, SSD saturado, GPU sem VRAM suficiente, cooler ruim, pasta térmica velha, VRM aquecendo, fonte instável. O Linux vai expor tudo isso com crueldade.
Eu considero o caso hardware-first quando vejo:
- throttling térmico persistente em
sensors; - pressão de memória alta mesmo sem swap relevante;
- NVMe com latência alta sob carga baixa;
- GPU em 99% com frame pacing ruim e VRAM no limite;
- queda de clock consistente após alguns minutos de estresse.
Se quiser confirmar temperatura e comportamento por vários minutos, rode uma carga mista e registre:
mkdir -p /tmp/perf-log
(while true; do date; sensors; cat /proc/pressure/cpu; cat /proc/pressure/memory; sleep 5; done) | tee /tmp/perf-log/telemetria.log
Isso me dá um histórico útil sem depender de memória visual. Em Linux, medir antes de mexer evita uma quantidade absurda de ajuste inútil.
Que baseline eu deixaria pronto para repetir em qualquer máquina?
Eu gosto de uma abordagem declarativa: kernel coerente, sysctl versionado, serviços sob controle, zram disponível, TRIM ativo, limits para builds e um método de observação pronto. Sem isso, cada máquina vira uma arte tribal.
Uma baseline mínima e honesta para desktop de performance ficaria assim:
{
"cpu_governor": "performance",
"swappiness": 10,
"vfs_cache_pressure": 50,
"zram": true,
"trim_timer": true,
"container_cpu_limit": 4,
"container_memory_limit_gb": 8,
"services_disabled": ["cups", "avahi-daemon", "bluetooth"]
}
Eu deixaria isso em repositório Git, junto com scripts de aplicação e rollback. Exemplo de script simples:
#!/usr/bin/env bash
set -euo pipefail
sudo cpupower frequency-set -g performance || true
sudo install -m 0644 /dev/stdin /etc/sysctl.d/99-desktop-performance.conf <<'EOF'
vm.swappiness=10
vm.vfs_cache_pressure=50
vm.dirty_background_ratio=5
vm.dirty_ratio=15
EOF
sudo sysctl --system
sudo systemctl enable --now fstrim.timer
Eu não gosto de improviso em máquina que precisa renderizar frames e compilar software pesado no mesmo dia. Desempenho do Linux se conquista com disciplina operacional, não com sorte. E o outro ponto é o mesmo: desempenho do Linux bom nasce de ajustes pequenos, verificáveis e reversíveis. Quando você trata CPU, memória, I/O e compositor como partes de uma pipeline, o sistema para de engasgar nos piores momentos e passa a responder como workstation de verdade — inclusive quando o jogo sobe, o container compila e o SSD trabalha no limite que foi feito para suportar.
Sou um profissional na área de Tecnologia da informação, especializado em monitoramento de ambientes, Sysadmin e na cultura DevOps. Possuo certificações de Segurança, AWS e Zabbix.


