2013-05-15 11 views
7

Vorrei utilizzare setTimeLimit per interrompere le operazioni bloccate in attesa (inattiva) dopo n secondi. Qui di seguito un esempio giocattolo in cui Sys.sleep è una chiamata segnaposto che è inattivo:setTimeLimit non riesce a terminare la chiamata in attesa in R

testlimit <- function(){ 
    setTimeLimit(elapsed=3, transient=TRUE); 
    Sys.sleep(10); 
} 

system.time(testlimit()); 

Tuttavia questo sta dando risultati inconsistenti. Su windows e in r-studio server (linux) la chiamata viene interrotta correttamente dopo 3 secondi win video. Tuttavia, quando eseguo questo in una sessione terminale su linux o osx, il timeout non viene attivato fino a dopo Sys.sleep() e lo script totale richiede 10 secondi per il completamento.

Che cosa causa questa differenza? C'è qualcosa che posso impostare nella sessione del terminale R in modo tale che il limite di tempo venga attivato? Sto usando Ubuntu 13.04 amd64, R versione 3.0.1 RC e osx 10.8

+0

Per quello che vale, ho appena provato questo su Ubuntu 12.04 + R3.0.0, Mac OSX + R 2.15.3 tramite interfaccia grafica e terminale e RStudio su entrambe le macchine.Sfortunatamente, non sono riuscito a riprodurre il tuo errore in nessuno di questi –

+0

Interessante. Quindi terminano tutti dopo 3 secondi nel tuo caso? Forse è un bug. Ho aggiunto un collegamento a un video per dimostrare il problema. – Jeroen

+1

effettivamente ... sessionInfo()? –

risposta

2

La domanda era answered by Simon Urbanek sulla mailing list r-devel. Di seguito una copia della sua risposta per riferimento futuro:

Che cosa causa questa differenza?

Il termine può essere controllato solo in R_ProcessEvents() così per tutti gli scopi pratici può essere attivata solo da codice interrompibile che chiama R_CheckUserInterrupt(). Ora, dipende interamente dal front-end per decidere come sarà il ciclo degli eventi. Ad esempio, la versione terminale di R non ha altri interrupt di cui preoccuparsi se non i gestori di input che si attivano in modo asincrono, quindi non è necessario eseguire alcun polling. Sys.sleep() si attiva solo sui gestori di input, quindi se non si dispone di alcun hook di origine evento esterno come gestore di input, non c'è motivo di elaborare alcun evento in modo che Sys.sleep() non veda alcun motivo per controllare il limite di tempo.

C'è qualcosa che posso impostare nella sessione R del terminale in modo tale che il limite di tempo venga attivato?

Su OS X in realtà è molto semplice: quartz(); dev.off() farà il trucco. Il motivo è che Quartz ha bisogno di forzare il ciclo degli eventi per elaborare gli eventi dalla finestra in modo asincrono. Lo fa installando un gestore di input basato su timer. Questo gestore farà in modo che Sys.sleep() si sveglia ogni 100 ms (è possibile modificare il valore utilizzando QuartzCocoa_SetLatency) in modo che si timeout con quella risoluzione: nessun

> testlimit <- function(){ 
+ setTimeLimit(elapsed=3, transient=TRUE); 
+ Sys.sleep(10); 
+ } 
> system.time(testlimit()); 
Error in Sys.sleep(10) : reached elapsed time limit 
Timing stopped at: 0 0.001 10.001 
> quartz(); dev.off() 
null device 
      1 
> testlimit <- function(){ 
+ setTimeLimit(elapsed=3, transient=TRUE); 
+ Sys.sleep(10); 
+ } 
> system.time(testlimit()); 
Error in Sys.sleep(10) : reached elapsed time limit 
Timing stopped at: 0.002 0.003 3.019 

Su Linux, non v'è built-in timer , quindi dovresti aggiungere un gestore di input che preverrà Sys.sleep(). Se vuoi un timer costante, puoi semplicemente prendere in prestito il codice da Quartz (dai un'occhiata a QuartzCocoa_SetupEventLoop in src/library/grDevices/src/qdCocoa.m) o al pacchetto CarbonEL. In realtà è solo una pipe che viene aggiunta come gestore di input in cui si scrive in modo asincrono quando si desidera riattivare il ciclo degli eventi. In cima alla mia testa non riesco a pensare a una soluzione integrata in R a questo punto (anche se si potrebbe sostenere che R potrebbe installare un gestore stesso quando viene impostato il limite ...).

Tuttavia, si noti che questo è solo un caso speciale di Sys.sleep(). Se si esegue effettivamente il codice R, ProcessEvents viene attivato automaticamente durante la valutazione (o nel codice C interrompibile).

Cheers, Simon

Problemi correlati