Danilo Poccia - Tecnologia et al.
DTrace in Solaris 10 OS
DTrace è un framework per il tracciamento dinamico delle attività svolte dal sistema operativo Solaris 10. Il framework è composto da tre componenti principali:
-
una serie di sonde (probe) introdotte nel kernel di Solaris 10 OS, che possono essere o meno attivate, descritte in dtrace(7D);
-
una libreria di interfacciamento per accedere dallo spazio utente alle funzionalità del framework, libdtrace(3LIB);
-
alcuni comandi utente che permettono di accedere in modo completo alle informazioni che sono rilevate, su richiesta, dalle sonde, tra cui il comando, omonimo del framework, dtrace(1M).
Alcuni comandi di
monitoraggio (ad es. lockstat, plockstat, intrstat) già presenti in
versioni precedenti del sistema operativo Solaris sono stati
re-implementati nella 10 tramite il framework DTrace.
Per vedere un esempio delle sonde è possibile lanciare il comando seguente e vedere le prime schermate:
# dtrace -l|more
Ogni sonda è individuata con un nome composto con la
sintassi seguente: "provider:module:function:name".
Per avere una idea della numerosità delle sonde è possibile lanciare il comando:
# dtrace -l|wc -l
e sottrarre uno per la riga di
intestazione. Quest'ultimo comando ritorna un numero superiore a
40.000 sul mio portatile con Solaris 10 1/06 x86 (32bit). Tale valore
dipende dai moduli kernel (che implementano DTrace) caricati sul
sistema.
Per testare le potenzialità di
DTrace è possibile realizzare degli script in un apposito
linguaggio denominato D
Programming Language. Tale linguaggio ha una sintassi
simile a quella dell'awk e non è quindi un linguaggio
puramente procedurale, ma del tipo "pattern action", dove il pattern è
un modo per selezionare alcune sonde e/o alcuni risultati particolari
delle sonde, mentre con l'action si identificano le attività
necessarie per elaborare le informazioni reperite.
Ad esempio un modo per registrarsi sulle sonde che monitorano le system call è possibile utilizzare il comando:
# dtrace -n 'syscall:::entry { trace(execname)}'|more
dove tra apici singoli è indicato il pattern ("syscall:::entry")
e tra le parentesi graffe l'azione corrispondente ("trace(execname)"). Il pattern,
che rispecchia la sintassi già indicata "provider:module:function:name",
non specificando il module e la function, si registra su tutte le sonde
che hanno provider="syscall" e
name="entry". L'action
indicata aggiunge, alle colonne standard dell'output del comando
dtrace(1),
il nome dell'eseguibile che ha effettuato la system call.
Lo stesso risultato si può ottenere
utilizzando il seguente script (syscall.d):
#!/usr/sbin/dtrace -s
syscall:::entry
{
trace(execname);
}
Per raggruppare i risultati della sonda che monitora le system call per nome dell'eseguibile che le ha effettuate e funzione, lo script è il seguente (syscall2.d):
#!/usr/sbin/dtrace -s
syscall:::entry
{
@numCalls[execname,probefunc] = count();
}
Andando invece a verificare le system call in scrittura, il seguente script (writes.d) raggruppa le chiamate per nome dell'eseguibile:
#!/usr/sbin/dtrace -s
syscall::write:entry
{
@numWrites[execname] = count();
}
Nel caso delle
scritture è però importante monitorare, oltre il numero
di accessi, la dimensione del blocco utilizzato. Difatti molti
problemi di performance sono poi legati proprio a questo aspetto. Le
linee guida generali (che vanno di volta in volta contestualizzate
all'architettura implementata) indicano che:
-
per letture/scritture sequenziali la dimensione del blocco dovrebbe essere "grande" (ad es. 32KB o superiori);
-
per letture/scritture random (ad es. via indice) la dimensione del blocco dovrebbe essere la più "piccola" che contiene la variazione richiesta con un unico accesso.
Il seguente script (writes2.d) restituisce per ogni eseguibile la dimensione media del blocco utilizzato nelle scritture via system call:
#!/usr/sbin/dtrace -s
syscall::write:entry
{
@avgSize[execname] = avg(arg2);
}
Con una semplice variazione (sostituendo la funzione avg con quantize) è possibile avere per ciascun eseguibile la distribuzione (su base potenze di 2) della dimensione del blocco utilizzato nelle scritture via system call (writes3.d):
#!/usr/sbin/dtrace -s
syscall::write:entry
{
@quantizeSize[execname] = quantize(arg2);
}
Per restringere l'analisi ad un solo
eseguibile, è sufficiente aggiungere un predicato di ricerca
tra doppi "/" (slash) nel pattern (writes4.d):
#!/usr/sbin/dtrace -s
syscall::write:entry
/execname == "soffice.bin"/
{
@quantizeSize[execname] = quantize(arg2);
}
Nel seguente esempio, in cui sono tracciate tutte le
attività di I/O (iotrace.d),
l'output standard del DTrace è disabilitato. Il pattern "BEGIN"
è utilizzato per attivare la corrispondente action una
volta all'inizio dell'esecuzione dello script, in questo caso per
stampare una riga di intestazione:
#!/usr/sbin/dtrace -qs
BEGIN
{
printf("%10s %58s %2s\n", "DEVICE", "FILE", "RW");
}
io:::start
{
printf("%10s %58s %2s\n",
args[1]->dev_statname,
args[2]->fi_pathname,
args[0]->b_flags & B_READ ? "R" : "W");
}
Per approfondire la sintassi e le funzionalità del framework è consigliabile consultare la Solaris Dynamic Tracing Guide.
Si possono utilizzare (e visionare) ulteriori script (più
complessi dei precedenti) scaricando l'ultima versione del DTraceToolkit dal sito della
comunità OpenSolaris.
Per ulteriori informazioni:
Posted at 02:11PM mar 02, 2006 by danilop in Solaris | Comments[0]


