2016-04-20 62 views
5

Sto vedendo molti usi di sleep 0 nel mio uno dei miei progetti client.sleep 0 ha un significato speciale?

Il codice è simile a questo.

while true 
    ... 
    ... 
    sleep 0 
end 

Leggendo alcune della risposta di così simile this sembra che sleep 0 ha una certa importanza.

Quello che voglio sapere ora è che la pianificazione per l'altro thread da eseguire (se sono in attesa di essere eseguiti) durante il periodo di tempo 0 è un lavoro di un VM lang come ruby ​​o python oppure è un lavoro del kernel .

In ordine, Ruby VM è in grado di onorare lo sleep 0 come indicato nel collegamento precedente.

risposta

5

Sì, per un paio di motivi, prima di tutto, i thread (mri) ruby ​​sono wrapper attorno ai thread nativi con un blocco GVL aggiuntivo.

In sostanza ciò che Ruby sta facendo quando chiami sonno chiama il sonno nativo, dipendente dalla piattaforma, e rilascia il GVL in modo che altri thread in esecuzione possano acquisirlo. Quindi, sleep(0) sta cedendo sia ad altri thread nativi che potrebbero essere in attesa di essere eseguiti, sia a rilasciare il blocco del thread corrente sul GVL che altrimenti impedirebbe l'esecuzione di Ruby VM.

Ecco un breve riassunto di come si può vedere questo da fonte mri:

  1. Otteniamo la definizione di Kernel sonno da https://github.com/ruby/ruby/blob/trunk/process.c#L7542, che vediamo è implementato in C nella funzione rb_f_sleep
  2. Il prossimo andare a rb_f_sleep e vedere che, nel caso di un unico argomento che chiama rb_thread_wait_for
  3. andare al rb_thread_wait_for definizione vediamo una chiamata a sleep_timeval
  4. sleep_timeval ha una chiamata a native_sleep
  5. native_sleep è dipendente dalla piattaforma e implementato in thread_pthread.c e thread_win32.c rispettivamente per i sistemi posix e windows. In entrambi i casi si vede chiamate a GVL_UNLOCK_BEGINhere e here

EDIT

Per essere più precisi:

di Windows:

L'implementazione di Windows di native_sleep utilizza WaitForMultipleObjects che fa effettivamente fornire la restante porzione di tempo, vedi: Does WaitForSingleObject give up a thread's time slice?

Posix:

L'attuazione posix utilizza pthread_cond_timedwait, che blocca il thread attualmente in esecuzione.

In entrambi i casi, la cosa principale da notare qui è che i thread di Ruby utilizzano i meccanismi di blocco dei thread sottostanti del sistema operativo e rilasciano il GVL con qualsiasi chiamata a sospensione, consentendo ad altri thread di assumere il controllo.

+1

Giusto per chiarire, detto questo, è improbabile che la persona che scrive quel blocco di codice stia davvero cercando di fare ciò che ho descritto, quindi dubito fortemente che queste chiamate di sonno possano essere utili o meno. In effetti, ogni volta che c'è un codice di applicazione rubino con una chiamata a dormire in esso sarei molto propenso a dire che è un odore di codice (anche se non sempre). – photoionized

+0

Ottima risposta. Hai familiarità con [Ruby Cross Reference] (http://rxr.whitequark.org/mri/ident?i=rb_f_sleep)? È un ottimo modo per esplorare la sorgente MRI. –

+0

@Jordan: risorsa eccezionale, sembra abbastanza simile a LXR, grazie per le informazioni! – photoionized