Queue vs Notifier

I Notificatori, come le code, sono utilizzati generalmente per comunicare attraverso due Loop paralleli oppure tra diversi VI in esecuzione sulla stessa macchina.
ProducerConsumer

Nel precedente articolo abbiamo parlato del funzionamento del Producer/Consumer Pattern, come si comportano le code e quali vantaggi possiamo trarre dal loro utilizzo.

In questo articolo volevo confrontare Queue e Notifier, descrivendo il loro utilizzo e le differenze principali.

I Notificatori, come le code, sono utilizzati generalmente per comunicare (passare i dati) attraverso due Loop paralleli oppure tra diversi VI in esecuzione sulla stessa macchina.

Per capire al meglio la similitudine, è utile dare un’ occhiata alle principali funzioni:

Obtain Notifier:
Crea un riferimento a una Notifica,bisogna specificare il tipo di dato.
Obtain Queue:
Crea un riferimento a una Coda,bisogna specificare il tipo di dato.
Send Notification:
Invia un messaggio a tutte le funzioni di notifica in attesa.
Enqueue:
Accoda un elemento per la funzione (una sola) Dequeue
Wait on Notification:
Attende finchè non riceve un messaggio, la funzione riceverà solo l’ultimo messaggio.
Dequeue Element:
Attende che ci sia almeno un elemento nella coda e li “scoda”
ovvero li rimuove presentandoli in uscita.
Release Notifier:
Rilascia il riferimento alla notifica, distruggendola.
Release Queue:
Rilascia il riferimento alla notifica, distruggendola.

Come si può notare le funzioni di Coda e quelle di Notifica si assomigliano molto, ma presentando differenze in come i dati vengono trattati.

Infatti possiamo dire che i Notifier non hanno memoria, solo l’ultimo dato inserito è disponibile, ma può avere molti lettori del dato in quanto la lettura non elimina il dato.

Le code invece hanno memoria (buffer FIFO o LIFO) ma possono avere un solo lettore che ne cancella il dato.

In pratica nel notifier il dato viene sostituito dallo scrittore, nelle code viene rimosso dal lettore che lo processa.

Il primo processo, aggiorna il notifier ogni 200ms.

Il secondo processo lo legge non appena è disponibile, ma prima di iterare nuovamente ha una funzione che lo rallenta di 200ms (simulato a titolo di esempio con il wait), per cui perderà informazioni.

Il terzo processo come per il secondo ha il dato ultimo aggiornato, ma probabilmente se la funzione di log impiega tempo perderà informazioni.

Se non ci interessa la perdita di informazioni, perchè magari il processo è molto lento.

Questo modello ci ha permesso di parallelizzare tre processi Acquisizione, Visualizzazione e Analisi/Log, notare che ci siano due processi in attesa dello stesso notifier.

Se invece abbiamo necessità di elaborare tutti i dati generati , dobbiamo ricorrere alle code, ricordando che in questo caso abbiamo solo un ricevitore, per cui per avere due consumer indipendenti si devono utilizzare due code.

In questo caso si deve notare l’effetto di avere i grafici alla fine dell’esecuzione identici ovvero tutti i dati generati sono stati processati, anche se i consumer hanno diversi tempi di iterazione..

Notare invece che abbiamo dovuto creare due code, una per ogni consumer.

Nota sul VI: Il For in uscita contiene un Get Queue Status, per attendere che i consumer abbiano scodato tutti gli elementi prima di terminali con destroy queue.

Un vantaggio comune è che i consumer non hanno necessità di temporizzazione (a meno che non sia necessaria per necessità di visualizzazione o altro) e non hanno polling, ottimizzando la percentuale di CPU richiesta.

Ovviamente le funzioni di notifica, come le Code, possono essere usate in combinazione con gli eventi, ciò permette appunto di sviluppare applicazioni con un interfaccia utente.

In conclusione si può quindi dire:

La funzione Notifier è adatta per comunicazioni dove è accettabile la perdita di dati beneficiando della relazione “Uno a Molti“, dove N ascoltatori processano un codice fino a quando questo non è sovrascritto.

La funzione Queue, al contrario, è adatta per comunicazioni senza perdita di dati con relazioni di tipo ” Molti a Uno“, dove multipli processi vengono memorizzati all’ interno del buffer di coda ed eseguiti da una singola funzione, senza perdità di dati.

Potrebbe interessarti anche

Refactoring in LabVIEW.

Il refactoring in LabVIEW è un processo di ristrutturazione di codice, funzionante correttamente, con lo scopo di renderlo leggibile, manutenibile ed espandibile.

Malleable VI

I VIM o VI malleable, sono Vi polimorfi sul dato. Sono da tenere in considerazione nella creazione delle proprie API.

Variabili Locali e Globali

Local e Global Variable sono utili, facili da implementare, ma attenzione a non abusarne. In questo articolo cerchiamo di vederne l'utilizzo migliore, almeno dal nostro punto di vista.

Manutenzione predittiva: significato e obiettivi

Cosa significa svolgere manutenzione predittiva? Effettuare interventi mirati sui macchinari, per prevenire i guasti con largo anticipo.

WATS e OEE

WATS ha migliorato una delle sue features più importanti: l’OEE. Il focus sulla produttività è una sfida costante per le imprese, non di meno in un settore competitivo come quello della manifattura elettronica.

La manutenzione predittiva

Manutenzione predittiva per intervenire sul macchinario prima che si guasti. Fermi di produzione evitati, riduzione costi e pianificazione interventi.