terça-feira, 31 de julho de 2012

Reduzindo o tempo de boot do OpenSUSE

Ter um boot - também conhecido como inicialização do sistema - rápido se tornou uma obsessão para muitos geeks há algum tempo atrás. Este artigo de Michal Vyskocil dá algumas dicas de como otimizar o tempo de boot do OpenSUSE, prometendo que o sistema inicie em até 2 segundos (!). Abaixo, publicamos os pontos principais.


Basicamente, há três possibilidades parafazer seu sistema iniciar mais rapidamente: iniciar as coisas em paralelo, iniciar as coisas na demanda ou iniciar menos coisas. Porém, como diz um famoso ditado, "Uma otimização prematura é a raiz de todo mal", assim, se temos de otimizar algo, antes de botar a mão na massa, precisamos saber o que fazer. Felizmente, o systemd vem com uma excelente ferramenta chamada systemd-analyse, que nos mostra o processo de boot de várias formas.


A simples execução desse comando exibe o tempo que fastamos em um processo de boot e em que fase:




# systemd-analyze
Startup finished in 8480ms (kernel) + 30873ms (userspace) = 39353ms


O exemplo acima mostra o tempo de boot em uma instalação mínima (com o X.org) da versão 12.2 em um netbook EEE 701. O tempo global é satisfatório, mas não nos ajuda a saber o que está acontecendo. Para nos ajudar, a ferramenta systemd-analyze possui dois subcomandos: blame e plot.


O subcomando blame imprime na tela os serviços que são iniciados, ordenados pelo tempo de partida. Aqueles que demoram mais para iniciar são os que devemos  colocar como os primeiros:




$ systemd-analyze blame | head
11385ms network.service
5664ms SuSEfirewall2_init.service
5575ms systemd-vconsole-setup.service
3032ms ntp.service
2840ms remount-rootfs.service
2230ms postfix.service
2021ms network-remotefs.service
1925ms cpufreq.service
1661ms SuSEfirewall2_setup.service
1506ms xdm.service


Já o sub comando plot cria um gráfico com os tempos de boot:


Exemplo de saída do comando systemd-analyze plot


Nesse exemplo, podemos ver que há uma longa cadeia com o SuSEfirewall12_init -> network -> network-remotefs -> suSEfirewall12_setup que demora vários segundos para ser finalizada. Essa configuração é ideal para um servidor, mas não para um laptop com poder de processamento reduzido, como o do autor do artigo.



Fazendo um notebook iniciar duas vezes mais rápido


Então, tendo as complexas dependências dos serviços em mente, o autor decidiu mascarar algumas delas, ou seja, fazer com que aquele serviço não possa ser iniciado pelo systemd, tornando-o invisível. No caso, o autor original fez essas mudanças:




  • Substituiu o network-service pelo NetworkManager, que é mais adequado para notebooks;

  • Desabilitou o suSEfirewall12_init e o suSEfirewall12_setup;

  • Desabilitou os serviços ntp.service e network-remotef.-service, que não faziam sentido em um laptop;

  • Desabilitou o postfix.service;

  • Desabilitou o cpufreq.service, pois ele não era suportado pela CPU do laptop.


Após as mudanças, houve redução no tempo de boot userspace:

$ systemd-analyze
Startup finished in 8528ms (kernel) + 11123ms (userspace) = 19652ms


Usando strace com systemd


Agora, ele tinha a lista desses serviços:

$ systemd-analyze blame | head -n 10
5476ms xdm.service
4172ms systemd-vconsole-setup.service
3950ms systemd-modules-load.service
2781ms remount-rootfs.service
1848ms NetworkManager.service
1439ms media.mount
1426ms systemd-remount-api-vfs.service
1419ms dev-hugepages.mount
1411ms dev-mqueue.mount
1371ms sys-kernel-debug.mount


Havia um novo gargalo, o systemd-vconsole-setup.service, porque ele atrasa o sysinit.target, que é um dos primeiros estágios do boot. Em casos como esse, podemos usar strace para saber o que está demorando tanto. E a depuração é bastante simples no mundo systemd. Tudo que temos a fazer é copiar o arquivo de serviço para  /etc/systemd/system e mudar o ExecStart:

ExecStart=/usr/bin/strace -f -tt -o /run/%N.strace /lib/systemd/systemd-vconsole-setup


Depois disso, temos de reiniciar. Você encontrará a saída do comando em /run/systemd-vconsole-setup.strace com um timestamp. Olhando lá, é óbvio que chamar hwinfo --bios é extremamente caro nesse estágio. Você pode acelerar a unidade ao configurar o KED_NUMLOCK para yes ou no no arquivo /etc/systemconfig/keyboard, ou tentar mascará-lo completamente.

O próximo serviço a ser olhado mais de perto é system-modules-load: systemd disse que ele levava 2 unidades de tempo na função init_module() do módulo microcode, que foi desabilitado.

Unidades nativas do systemd


Havia um pequeno script de inicialização chamado purge-kernels, que era iniciado por volta dos 300ms de acordo com o blame. Neste caso, foi mais efetivo porque o systemd faz apenas um stat no arquivo e não o roda completamente, fazendo esse serviço desaparecer do blame:

$ cat /etc/systemd/system/purge-kernels.service
[Unit]
Description=Purge old kernels
After=local_fs.target
ConditionPathExists=/boot/do_pure_kernels

[Service]
Type=oneshot
ExecStart=/sbin/purge-kernels


O tempo do kernel


Havia algo interessante sobre o tempo do kernel: 8 segundos gastos parecia ser um monte de tempo para ele. Um simples ls na pasta /boot deu uma direção:

$ ls -lh /boot/vmlinuz-* /boot/initrd-*
-rw-r--r-- 1 root root 14M Jul 24 11:03 /boot/initrd-3.4.4-1.1-desktop
-rw-r--r-- 1 root root 4.7M Jul 10 15:48 /boot/vmlinuz-3.4.4-1.1-desktop


Como você pode notar, o initrd era enorme, cerca de três vezes o tamanho do kernel. O que teria causado isso? Bem, cada pacote pode adicionar seus próprios scripts de configuração em /lib/mkinitrd/scripts/, assim vamos perguntar ao rpm quem fez isso:

$ rpm -qf /lib/mkinitrd/scripts/setup-* | sort -u
cifs-utils-5.5-2.2.2.i586
cryptsetup-1.4.2-3.2.1.i586
device-mapper-1.02.63-26.1.1.i586
dmraid-1.0.0.rc16-18.2.1.i586
kpartx-0.4.9-3.1.1.i586
lvm2-2.02.84-26.1.1.i586
mdadm-3.2.5-3.3.2.i586
mkinitrd-2.7.0-62.2.1.i586
multipath-tools-0.4.9-3.1.1.i586
plymouth-scripts-0.8.5.1-1.3.1.noarch
splashy-0.3.13-35.1.1.i586


Com essa lista em mãos, o autor começou a desinstalar coisas que ele não precisava:

  • cifs-utils: se você não tem qualquer disco formatado em sistemas de arquivos Windows para montar, pode removê-lo, mas não influencia no tamanho do kernel;

  • cryptsetup:  serviço popular para laptops, mas o autor não tinha quaisquer dispositivos luks. Ele também remove uma parte do Yast e, assim, ele economizou 18 MB em disco.

  • device-mapper, dmraid, kpartx e lvm2: não podem ser facilmente removidos por muitas coisas de baixo nível dependerem delas. Mantido.

  • mdadm: não havia dispositivos md, removido.

  • mkinitrd: sua remoção poderia reduzir o tamanho do initrd para zero mas, aí, precisaríamos do nosso próprio kernel.

  • multipath-tools: sem dispositivos multipath; removido;

  • plymouth-scripts: quem precisa daquela tela de boot bonitinha quando se pode iniciar mais rápido? Sua remoção reduziu o initrd para 8,9MB.

  • splashy: o mesmo - e dessa vez reduziu o initrd para 6,6 MB.


Após as mudanças, o tempo de boot do kernel caiu quase que pela metade:

$ systemd-analyze
2781ms (kernel) + 4999ms (userspace) = 7780ms


Conclusão


Os serviços que deixam o boot mais "bonitinho" também são as que o tornam mais demorados. Perceba que, aqui, o autor não seguiu aquelas fórmulas mágicas encontradas em vários tutoriais que nos mandam desabilitar x, y e z: ele pesquisou e descobriu o que estava atravancando a inicialização do seu sistema. É isso que você deve fazer: utilizar as ferramentas que foram mostradas aqui para analisar o seu computador e decidir o que pode o que não pode cair fora.

3 comentários:

  1. Reduzindo o tempo de boot do OpenSUSE - http://t.co/gtVjq8ql #blog

    ResponderExcluir
  2. Reduzindo o tempo de boot do OpenSUSE: Blog Espaço LiberdadeTer um boot – também conhecido como inicialização do... http://t.co/XzayBlnX

    ResponderExcluir
  3. Boa noite, seguidores. Já leram nossos posts de hoje? http://t.co/sEhCc7jw http://t.co/drvvZ9Zd

    ResponderExcluir