Chiunque si lasci tentare dalla sfida del momento di accorciare il più possibile il tempo di avvio della propria macchina si imbatte prima o poi nell'idea di lanciare gli script di init in parallelo.
L'impresa è apparentemente molto semplice: basta aggiungere la variabile
CONCURRENCY=shell nel file /etc/default/rcS
e il gioco è fatto.
In realtà se contemporaneamente non si ristudia anche la sequenza degli script, i risultati tarderanno a farsi notare. Se poi readahead è installato, potrebbe riservare spiacevoli sorprese...
Partiamo proprio da quest'ultimo: l'installazione di readahead piazza uno script di avvio in /etc/init.d
e crea il link simbolico /etc/rcS.d/S02readahead
. Fintantoché gli script delle directory /etc/rc?.d
sono eseguiti in base all'ordine alfabetico del loro nome, questo script è chiamato dopo S02mountkernfs
. Ciò è corretto perché readahead presume che /proc
sia montato, che è esattamente ciò che fa mountkernfs.
Ma cosa succede se, avendo indicato CONCURRENCY=shell
, tutti gli script con lo stesso ordine di avvio (o priorità) sono lanciati in parallelo? In questo caso readahead e mountkernfs, entrambi con priorità 02, sono eseguiti insieme e non c'è alcuna garanzia che il secondo abbia già montato /proc
quando il primo ne ha bisogno.
Riorganizzazione di rcS.d
In pratica readahead deve essere lanciato dopo mountkernfs (priorità 02), ma prima di udev (priorità 03). Poiché non esiste una priorità "due e mezzo", l'unica soluzione è "promuovere" udev alla priorità 04. Ciò a sua volta impone che tutti gli script successivi che dipendono l'uno dall'altro siano anch'essi promossi a cascata: mountdevsubfs (da 04 a 05), e keymap e bootlogd (da 05 a 06).
A questo punto la sequenza è sicura, ma non ancora ottimizzata. Per ottenere qualche beneficio dall'esecuzione parallela, è necessario che ogni livello di priorità contenga il maggior numero possibile di script, in modo da massimizzare i processi che possono girano in parallelo. Ci sono sei interventi da fare per migliorare le cose:
- hdparm e hwclockfirst dipendono solo da mountdevsubfs (priorità 05), perciò si possono spostare al livello 06;
- ancora prima, procps non sembra dipendere da niente e può quindi essere lanciato subito dopo readahead, alla priorità 04, in parallelo con udev;
- ifupdown-clean, module-init-tools, mtab e udev-mtab richiedono solo che il file system di root siavalidato, quindi trovano collocazione ottimale alla priorità 12, subito dopo checkroot;
- un altro gruppo di script che vanno a braccetto è il trio x11-common, urandom e ifupdown, che richiedono un file system locale stabile, ma non hanno esigenze di rete: la priorità più logica per loro è 39, immediatamente prima di networking;
- poiché 39 è anche la priorità predefinita di readahead-desktop e visto che questo può svolgere meglio la sua funzione di precaricamento se lo si lascia girare da solo, suggerisco di anticiparne l'esecuzione al livello 38;
- infine, il gruppo constituito da console-screen, alsa-utils, sudo e bootmisc può appropriarsi della priorità 50.
Nota: ho saltato di proposito hwclock, perché sinceramente non ho mai capito quale funzione svolga questo script che non sia già egregiamente svolta da hwclockfirst. In ogni caso, sono riuscito a liberarmi di entrambi questi lentissimi script semplicemente delegando al kernel la lettura dell'orologio, grazie al supporto RTC.
In conclusione, ecco come dovrebbe apparire la directory /etc/rcS.d
dopo la "cura", dove gli script con la stessa priorità sono indicati sulla stessa riga:
S01glibc S02hostname S02mountkernfs S03readahead S04udev S04procps S05mountdevsubfs S06bootlogd S06hdparm S06hwclockfirst S06keymap S10checkroot S12ifupdown-clean S12module-init-tools S12mtab S12udev-mtab S30checkfs S35mountall S36mountall-clean S37mountoverflowtmp S38readahead-desktop S39ifupdown S39urandom S39x11-common S40networking S45mountnfs S46mountnfs-bootclean S50alsa-utils S50bootmisc S50console-screen S50sudo S99stop-bootlogd-single
Riorganizzazione di rc2.d
Soddisfatti dell'ottimo lavoro fatto su rcS.d
, possiamo passare ad analizzare anche rc2.d. Qui però l'obiettivo è differente. Ciò che veramente ci interessa è raggiungere il più in fretta possibile la schermata di login, tutto il resto può seguire al ritmo che vuole.
Per semplicità, assumiamo che il login sia gestito da GDM. La configurazione di altri display manager dovrebbe essere più facile e per questo lasciata al lettore come esercizio!
La prima cosa da fare è identificare il "cammino critico" che porta il più velocemente possibile ad eseguire S30gdm
. Eccolo:
S10sysklogd -> S12dbus -> S24hal -> S30gdm
Aggiungerei anche S11klogd, per essere sicuri di non perdere qualche messaggio del kernel in questa fase. Tutto il resto può venire dopo, con la maggioranza degli script alla priorità 40, tranne le seguenti eccezioni:
- system-tools-backend potrebbe servire alla sessione GDM che sta partendo, quindi gli assegniamo la priorità 31;
- gli script saned e cups, che dipendono da avahi-daemon, vanno spostati al livello 45;
- possiamo decidere di lasciare cron e anacron alla loro priorità predefinita di 89 perché, per loro stessa natura, svolgono funzioni che non devono necessariamente essere espletate all'avvio;
- in coda alla seuqenza di avvio, gli ultimi script vanno leggermente riarrangiati: rmnologin e rc.local vanno eseguiti al livello 98, cioè subito prima degli "ultimissimi" script, che sono stop-bootlogd, stop-readahead ed eventualmente bootchart.
Ecco come dovrebbe apparire la directory /etc/rc2.d
ottimizzata:
S10sysklogd S11klogd S12dbus S24hal S30gdm S31system-tools-backend S40acct S40avahi-daemon S40openbsd-inetd S40ssh S45cups S45saned S89anacron S89cron S98rc.local S98rmnologin S99bootchart S99stop-bootlogd S99stop-readahead
Naturalmente, la lista potrebbe cambiare di molto al variare del software installato. Ad esempio, xinetd potrebbe aver preso il posto di openbsd-inetd
, etc. Inoltre avahi-daemon non è strettamente necessario: CUPS e sane funzionano anche senza!
Prima di concludere, è obbligatorio citare il pacchetto insserv che promette di fare quanto sopra in modo automatico. Sinceramente sconsiglio questo pacchetto: la sequenza riordinata da insserv, benché corretta dal punto di vista delle dipendenze, è totalmente scorrelata dalla funzione che svolge ciascuno script. Ad esempio, insserv non può sapere che vogliamo GDM attivo il più presto possibile.
Quanto sopra è il risultato dell'ottimizzazione che ho studiato sul mio sistema e che mi ha permesso di risparmiare 3 secondi all'avvio. Auguro a tutti di ottenere risultati analoghi!
Commenti
Inviato da ntropia il Dom, 22/03/2009 - 00:42.
Apprezzamento
C'è poco da dire: un bel lavoro.
eNjoy
Chi ha intendimento conti il numero della Bestia, perché è un numero d'uomo; e il suo numero è...
rw-rw-rw-
Inviato da paco_deb il Dom, 29/03/2009 - 13:36.
Integrazione guide
Indubbiamente un articolo accurato anche se questi argomenti erano già stati trattati nella guida peedUp Linux Boot - Velocizzare l'avvio di Debian in cui spiegavo come ridurre il tempo di boot.
Tra l'altro esiste un software (insserv) che in automatico analizza le dipendenze degli script e ne ristabilisce l'ordine al fine si velocizzare la procedura di startup.
Resta comunque il fatto che l'analisi e la comprensione così profonda degli script d'avvio è comunque un lavoro lodevole, senza contare sche se non sbaglio insserv non si fa carico di riorganizzare il runlevel comune (rc.S).
Sarebbe interessante a mio parere integrare gli articoli in un unica guida mirata alla completa comprensione e velocizzazione della procedura d'avvio, argomento tanto caro a chi utilizza debian su notebook.
Ciao
----------------
E.C.: scusa, non avevo notato che avevi già citato insserv, purtroppo ho il maledetto vizio di usare la lettura veloce anche quando non dovrei, principalmente per pigrizia.
PS: Mi veniva da pensare che determinate modifiche potrebbero essere automatizzate mediante l'installazione di un deb, se ti interessa fammi sapere
Ciao
Paco - http://dmp.altervista.org/
Inviato da mcortese il Lun, 30/03/2009 - 19:07.
Re: Integrazione guide
Quote:
Sono d'accordo: sarebbe utilissima. Tra l'altro ho un paio di considerazioni che sono emerse dall'epoca della guida, che non ho ancora trovato il tempo di mettere giù per iscritto. Vedi, ad esempio, il prossimo commento...
Inviato da mcortese il Lun, 30/03/2009 - 19:19.
Bug #519520
Avete seguito i consigli della guida ma non avete ottenuto i risultati sperati? Vi sembra che l'esecuzione degli script rimanga sostanzialmente ed inesorabilmente sequenziale?
Ebbene, sappiate che la colpa non è vostra. È il frutto di una policy assurda e di uno script troppo zelante.
La spiegazione è nel bug #519520. In breve: gli script che hanno l'estensione ".sh" vengono trattati diversamente da tutti gli altri e non vengono eseguiti in parallelo.
In attesa che il baco venga risolto a monte dal manutentore del pacchetto sysv-rc, potete ricorrere a questo semplice trucchetto.
Editate il file /etc/init.d/rc e sostituite tutte le stringhe "*.sh)" con "*.sh-falso)" o qualsiasi altra stringa che non corrisponda a dei nomi di file validi.
Dopo questa sostituzione, gli script .sh non saranno trattati diversamente dagli altri.
Inviato da mcortese il Mer, 24/06/2009 - 11:52.
Re: Bug #519520
La versione 2.86.ds1-62 di sysvinit (appena caricata in unstable) ha corretto questo baco. Dal changelog:
Quote:
In altre parole, gli script con estensione .sh non saranno trattati in modo diverso dagli altri in /etc/rcS.d...