Socket, irb e prestazioni

Permesso e ciao a tutti.
Come sempre succede nei forum, il mio primo accesso qui coincide con una
domanda.

Sto sviluppando un insieme di classi (ovviamente in ruby) che hanno lo
scopo di gestire la registrazione dell’output di un dispositivo di
misura.
Il dispositivo in questione è dotato di una interfaccia ethernet con un
protocollo binario proprietario ma aperto. La classe che ho scritto si
occupa di aprire una connessione via socket (TCPSocket) con il
dispositivo e fornisce una serie di metodi per accedere alle
funzionalità del dispositivo di misura, tra cui il metodo più importante
che - ovviamente - legge i valori misurati.
Il mio scopo è interrogare il dispositivo con una frequenza che sia
almeno pari a 100 Hz.
Se invoco il metodo di lettura valori all’interno di un ciclo while in
irb ottengo frequenze superiori ai 700 Hz, su una comune rete 100Mbit,
con un paio di switch di mezzo e su due sottoreti differenti. Vaore
ottimale e più che sufficiente. Si noti che ogni chiamata trasferisce
meno di 1000 byte.
Se invece invoco il metodo all’interno di uno script stand-alone, la
frequenza cala brutalmente, e non è mai superiore a 60 Hz.
Ho notato che se prima di chiamare il metodo inserisco uno sleep 10 la
situazione migliora leggermente (tipicamente passo da 20 a 60 Hz) e
questo immagino sia dovuto ai meccanismi di precompilazione e caching
dell’interprete.
Resta comunque una impressionante differenza tra irb e l’interprete
ruby: qualcun o di voi sa a cosa potrebbe essere dovuta?

Ad onore di ruby, devo dire che la stessa classe l’ho scritta anche in
C++ e Objective-C, ottenendo prestazioni assolutamente paragonabili
(circa 700 Hz). Ovviamente la classe in Ruby l’ho scritta in metà righe
e un quarto del tempo!

Se qualcuno ha esperienza su problemi analoghi e/o ha interesse ad
approfondire l’argomento…
Grazie!

— Paolo B. [email protected] wrote:

Resta comunque una impressionante differenza tra irb
e l’interprete
ruby: qualcun o di voi sa a cosa potrebbe essere
dovuta?

irb è solo uno script, quindi non dovrbbe esseri
alcuna differenza. O meglio, forse dovrebbe essere più
lento.
Due idee:

  1. forse stai usando windows? I processi “in primo
    piano” su windows ottengonoi un trattamento speciale
    dallo scheduler.
  2. forse la garbage collection o l’allocazione di
    oggetti ti sta fregando in qualche modo i.e. c’è uno
    scarto prestazionale anche solo tra

a=nil
n.times { a=i }
e
n.times { a=i }

Comunque se potessi mandare il codice e fosse
relativamente piccolo magari potresti ricevere più aiuto.

  ___________________________________________________________

Yahoo! Mail is the world’s favourite email. Don’t settle for less, sign
up for
your free account today
http://uk.rd.yahoo.com/evt=44106/*http://uk.docs.yahoo.com/mail/winter07.html

irb � solo uno script, quindi non dovrbbe esseri
alcuna differenza. O meglio, forse dovrebbe essere pi�
lento.

In effetti, è esattamente quello che mi aspettavo. Ma la realtà a volte
supera l’immaginazione…

Due idee:

  1. forse stai usando windows? I processi “in primo
    piano” su windows ottengonoi un trattamento speciale
    dallo scheduler.

Windows? cos’è windows? non lo conosco…
Per il resto, ho osservato lo stesso comportamento sotto OS X, sotto
Gentoo e sotto PCBSD, e in ogni caso indipendentemente dal livello di
priorità del processo (anche con un nicelevel -20)

  1. forse la garbage collection o l’allocazione di
    oggetti ti sta fregando in qualche modo i.e. c’� uno
    scarto prestazionale anche solo tra

Tutte le variabili nei blocchi sono predichiarate. In effetti, sto
pensando di riscrivere una versione semplificata della classe, tanto per
isolare il problema e tnato per avere una versione abbastanza compatta
da poter essere postata qui (tra l’altro, quella che ho a disposizione
al momento non funziona se non è connessa allo strumento).

Grazie mille per la risposta, Gabriele
P.

Matteo V. wrote:

On 4/13/07, Paolo B. [email protected] wrote:

dispositivo e fornisce una serie di metodi per accedere alle
frequenza cala brutalmente, e non � mai superiore a 60 Hz.
Se sostituisci all’istruzione che parla con la rete una sleep di 1
millisecondo che cosa succede? Dovresti arrivare a circa 1KHz sia in
irb che nello script, giusto? Solo per capire se dipende da come usi
la rete.

Hai provato ad osservare il traffico di rete nei due casi? I
pacchetti sono gli stessi, anche se pi� lenti?

Hai provato a disabilitare l’algoritmo di Nagle?

M

Dopo una giornata di prove di ogni genere sono più confuso di prima…
Se sostituisco l’istruzione con uno sleep di 1 secondo il problema non
si presenta, e anche settando il TCP_NODELAY (è questo che intendi con
Nagle, vero?) non c’è nessuna differenza.
Tuttavia ho notato una cosa: se si osserva il traffico con ethereal,
ogni comunicazione con la TCPSocket in ruby presenta dei pacchetti con
un checksum errato. Succede anche a voi? è un problema limitato alla
libreria Socket sotto OS X?

Matteo, grazie per i consigli,
P.

Se sostituisco l’istruzione con uno sleep di 1 secondo il problema non
si presenta,

eeps… 1 MILLIsecondo, volevo dire…

On 4/13/07, Paolo B. [email protected] wrote:

dispositivo e fornisce una serie di metodi per accedere alle
frequenza cala brutalmente, e non è mai superiore a 60 Hz.
Se sostituisci all’istruzione che parla con la rete una sleep di 1
millisecondo che cosa succede? Dovresti arrivare a circa 1KHz sia in
irb che nello script, giusto? Solo per capire se dipende da come usi
la rete.

Hai provato ad osservare il traffico di rete nei due casi? I
pacchetti sono gli stessi, anche se più lenti?

Hai provato a disabilitare l’algoritmo di Nagle?

M

On 4/16/07, Paolo B. [email protected] wrote:

Hai provato ad osservare il traffico di rete nei due casi? I
pacchetti sono gli stessi, anche se pi� lenti?

Hai provato a disabilitare l’algoritmo di Nagle?

M

Dopo una giornata di prove di ogni genere sono più confuso di prima…
Se sostituisco l’istruzione con uno sleep di 1 secondo il problema non
si presenta,

Ottimo! Dunque è un problema di socket/rete/protocolli.

e anche settando il TCP_NODELAY (è questo che intendi con

Nagle, vero?) non c’è nessuna differenza.

OK. Almeno questo lo abbiamo escluso.

Tuttavia ho notato una cosa: se si osserva il traffico con ethereal,

ogni comunicazione con la TCPSocket in ruby presenta dei pacchetti con
un checksum errato. Succede anche a voi? è un problema limitato alla
libreria Socket sotto OS X?

Fa differenza se usi irb?

Un’altra cosa che potresti fare è provare diverse versioni di Ruby
oppure
usare un sistema operativo differente.

M