2010-01-06 9 views
7

Sto eseguendo molte ricerche di file in base a un criterio in più iterazioni dal mio script Perl e sembra occupare il 100% del tempo della CPU. C'è un modo per controllare il mio utilizzo della CPU dello script? Ho letto da qualche parte su come inserire cicli di sonno vuoti nella mia sceneggiatura. Ma non sono sicuro di come farlo.Controllare l'utilizzo della CPU di uno script perl?

+0

Questo dipende dalla piattaforma. Su quale sistema operativo stai funzionando? –

+1

@bish Se non ci sono altri processi che necessitano della CPU, perché dovrebbe lasciarlo, sprecare cicli buoni quando possono essere messi a frutto? – Eli

+0

Sto eseguendo i miei script su Windows. Sì, ci sono anche altri processi in esecuzione. Dovevo essere meno invadente con le mie sceneggiature. –

risposta

10

si potrebbe abbassare il processo di priorità (di Perl), come assegnato dal sistema operativo: windows o linux

esempio per priorità più bassa:

finestre

start /LOW perl <myscript> 

linux

nice +19 perl <myscript> 
+0

Questa sembra la soluzione più semplice. Proverò questo prima degli altri e riferirò. –

+0

Questa è una soluzione semplice ma richiede la conoscenza degli utenti o la creazione di uno script di avvio o di un alias. Se, tuttavia, si utilizza setpriority(), il codice ridice/modifica sempre la priorità come previsto. Il tipo di applicazione e uso dovrebbe decidere quale soluzione scegliere. –

3

solo dormire:

while ($not_done_yet) { 
    do_stuff_here(); 
    sleep 1; # <-- sleep for 1 second. 
} 

o poco più di fantasia, fare operazioni N per ciclo del sonno:

my $op_count = 0; 
while ($not_done_yet) { 
    do_stuff_here(); 

    $op_count ++; 
    if ($op_count >= 100) { 
     $op_count = 0; 
     sleep 1; # <-- sleep for 1 second every 100 loops. 
    } 
} 
+0

Ok. Ho un'idea. Quindi dovrò suddividere i miei compiti in gruppi che possono essere ripetuti. –

5

Si potrebbe utilizzare sleep or usleep. Un'altra cosa che puoi fare è abbassare la priorità del processo.

Aggiornamento: Vedi setpriority()

+0

La funzione 'setpriority' di Perl è solo un wrapper attorno alla chiamata di sistema con lo stesso nome. In quanto tale, è un errore fatale chiamarlo su piattaforme che non lo implementano (ad esempio Windows). –

+0

Ho appena confermato questo. 'setpriority()' non è implementato in Windows. –

7

Un ottimo modo per migliorare l'utilizzo della CPU è quello di utilizzare gli algoritmi migliori. Non indovina dove il tuo codice spende tutto il suo tempo: usa un profiler. Devel::NYTProf è uno strumento fantastico per questo.

Ricordarsi di mantenere Amdahl's law in mente. Ad esempio, diciamo che parte del tuo programma usa un algoritmo quadratico e con qualche sforzo potresti sostituirlo con uno lineare. Evviva! Ma se il codice in questione rappresenta solo il 5% del tempo di esecuzione totale, il tuo sforzo più eroico non può portare a risultati migliori di un piccolo miglioramento del cinque percento. Utilizza un profiler per determinare se le opportunità di maggiore velocità sono disponibili altrove.

Lei non ci dici quello che stai cercando, e anche i più noti algoritmi può essere intensivo della CPU. Considera che lo scheduler del tuo sistema operativo è stato scritto, sintonizzato manualmente, testato e riscritto per utilizzare le risorse di sistema in modo efficiente. Sì, alcune attività richiedono scheduler specializzati, ma tali casi sono rari, anche meno probabili dato che si sta utilizzando Perl.

Non prenderlo come un brutto segno che il tuo codice sta consumando CPU. Si può essere sorpresi di apprendere che una delle sfide più difficili di sistemi in tempo reale, dove le prestazioni è fondamentale, è quello di mantenere occupata la CPU, piuttosto che al minimo.

+0

Il mio script impiega molto tempo a svolgere attività umili, come cercare testo nei file, eseguire programmi esterni, catturare e analizzare il loro output, piuttosto che qualsiasi algoritmo specializzato. In generale, sono d'accordo con la tua opinione. Non sono particolarmente preoccupato del fatto che il mio copione stia divorando la CPU. Ma più con il fatto che questo utilizzo della CPU sta influenzando altri programmi e servizi in esecuzione sullo stesso server Windows. Quindi è così. Una semplice priorità bassa del processo sembra al momento servire al mio scopo. Sì, la profilazione è buona a lungo termine. –

+0

Sembra una scelta intelligente. –

+0

Grazie per il suggerimento su NYTProf! note to self: l'unico tipo di guida con i passaggi che ho trovato finora è [perlmonks: mod_perl application profiling - Problem] (http://www.perlmonks.org/?node_id=833194) .. Saluti! – sdaau

2

sleep + time + times può fare questo.

my $base = time; 
my $ratio = 0.5; 
my $used = 0; 
sub relax { 
    my $now = time; 
    my ($total) = times; 
    return if $now - $base < 10 or $total - $used < 5; # otherwise too imprecise 
    my $over = ($total - $used) - $ratio * ($now - $base); 
    $base = $now + ($over > 0 && sleep($over)); 
    $used = $total; 
} 

(testato ...) Cospargere abbastanza relax chiamate in tutto il codice e questo dovrebbe mediare al vicino o sotto il tempo di CPU del 50%.


BSD::Resource può fare questo meno invasivo, e si potrebbe anche prendere Time::HiRes per una maggiore precisione.

my $base = clock_gettime(CLOCK_MONOTONIC); 
my (undef, $hard) = getrlimit(RLIMIT_CPU); 
my $interval = 10; 
if ($hard != RLIM_INFINITY && $hard < $interval) {$interval = $hard/2} 
my $ratio = 0.5; 
$SIG{XCPU} = sub { 
    setrlimit(RLIMIT_CPU, $interval, $hard); 
    my $now = clock_gettime(CLOCK_MONOTONIC); 
    my $over = $interval - $ratio * ($now - $base); 
    $base = $now + ($over > 0 && sleep($over)); 
}; 
setrlimit(RLIMIT_CPU, $interval, RLIM_INFINITY); 

(anche non testata ...) In un sistema che lo supporta, questo dovrebbe chiedere al sistema operativo per segnalare voi ogni $interval secondi di tempo di CPU, a questo punto viene azzerato il contatore e il sonno. Questo non dovrebbe richiedere alcuna modifica al resto del codice.

+0

deve essere testato. Ma sembra una soluzione interessante per controllare in generale l'utilizzo della CPU con i numeri. –

2

Il tuo script sta effettivamente facendo le cose tutto il tempo? Ad esempio, se si calcola un set di mandelbrot, si avranno loop che consumano CPU, ma stanno elaborando attivamente i dati per tutto il tempo.

O avete i cicli in cui si è in attesa di ulteriori dati da elaborare:

while(1) { 
    process_data() if data_ready(); 
} 

Nel primo caso, l'impostazione priorità è probabilmente la soluzione migliore. Questo rallenterà il calcolo, ma solo quanto necessario per servire qualsiasi altro processo sul sistema.

Nel secondo caso, è possibile migliorare drasticamente l'utilizzo della CPU dormendo solo per una frazione di secondo.

while(1) { 
    process_data() if data_ready(); 
    select(undef, undef, undef, 0.1); 
} 

Se si sta tirando i dati da una fonte che select può operare su, tanto meglio. Puoi organizzare il blocco del tuo loop finché i dati non sono pronti.

use IO::Select; 
my $s = IO::Select->new($handle); 

while(1) { 
    process_data() if $s->can_read; 
} 

Select funziona su prese e file-maniglie sistemi * nix. Sui sistemi Windows, è possibile selezionare solo contro socket.