È necessaria una coda Python per un semplice flusso di byte tra thread?
-
08-07-2019 - |
Domanda
Ho un semplice thread che prende byte da un socket RFCOMM Bluetooth (simile a una porta seriale) e li scarica in un Queue.Queue
(FIFO), che sembra il metodo tipico per lo scambio dati tra thread. Funziona bene.
Ma questo è eccessivo? Potrei semplicemente usare un bytearray e avere il mio thread del lettore .append (somebyte)
e la funzione di elaborazione solo .pop (0)
? Non sono sicuro che le protezioni in Queue siano pensate per code "multi-produttore, multi-consumatore" più complesse e uno spreco per un flusso di byte da punto a punto. Fare cose come svuotare la coda o catturare più byte sembra più imbarazzante con la coda rispetto a un tipo di dati più semplice.
Suppongo che la risposta potrebbe avere a che fare se .pop ()
è atomico, ma importerebbe anche allora? ...
Soluzione
Con Queue
, sei garantito di essere thread-safe in qualsiasi implementazione e versione di Python. Basandosi su questo o quel metodo di un altro oggetto che è "atomico" (in una data implementazione e versione) in genere ti lascia in balia di questa "atomicità" non essendo una garanzia forte (solo un artefatto di implementazione per lo specifico rilascio di punti e amp; c che stai usando) e quindi condizioni di gara MOLTO difficili da mettere in debutto che vengono introdotte con qualsiasi aggiornamento o porta ad altre implementazioni di Python.
Se la tua profilazione ti dice che le garanzie forti e generali di Queue
rappresentano un collo di bottiglia per il tuo specifico caso d'uso produttore-consumatore, rendi la tua coda FIFO più sicura garantita da thread / ruscello. Ad esempio, se hai scoperto che (al netto delle condizioni di gara) append
e pop
sarebbero perfetti per il tuo uso, crea una classe che protegga ciascuno con un lucchetto acquisisci / rilascia (usa una con
) - Queue
aggiunge un sovraccarico minuscolo per supportare più produttori e consumatori e puoi eliminare quei pochi nanosecondi! -)
Altri suggerimenti
Sì, pop () è atomico, ma resterei fedele a Queue se le prestazioni non sono molto importanti.
Se la velocità di input è abbastanza veloce, puoi sempre bufferizzare i byte in una stringa prima di spingerli nella coda. Ciò probabilmente aumenterà il throughput riducendo la quantità di blocchi effettuati, a scapito di un po 'di latenza aggiuntiva sul lato ricevente.