2010-05-28 21 views
15

Sto cercando un modo per eseguire la registrazione asincrona e thread-safe nel mio progetto C++, se possibile su un file. Attualmente sto utilizzando cerr e clog per l'attività, ma poiché sono sincroni, l'esecuzione si interrompe brevemente ogni volta che viene registrato qualcosa. È un'app relativamente pesante per la grafica, quindi questo genere di cose è abbastanza fastidioso.Registrazione asincrona thread-thread in C++

Il nuovo logger deve utilizzare l'I/O asincrono per eliminare queste pause. Sarebbe anche auspicabile la sicurezza del thread, visto che intendo aggiungere presto del multithreading di base.

Ho considerato un approccio one-file-per-thread, ma sembrava che avrebbe reso la gestione dei registri un incubo. Eventuali suggerimenti?

risposta

4

Questo è MOLTO possibile e pratico. Come lo so? Ho scritto esattamente questo nel mio ultimo lavoro. Sfortunatamente (per noi), ora possiedono il codice. :-) Purtroppo non lo usano nemmeno.

Ho intenzione di scrivere una versione open source nel prossimo futuro. Nel frattempo, posso darti qualche suggerimento.

  1. I manipolatori I/O sono in realtà solo nomi di funzioni. Puoi implementarli per la tua classe di registrazione in modo che il tuo logger sia compatibile con Cout/Cin.
  2. Le funzioni del proprio manipolatore possono tokenizzare le operazioni e memorizzarle in una coda.
  3. Una coda può essere bloccata su quella coda aspettando che pezzi di log vengano a galla. Quindi elabora le operazioni di stringa e genera il log effettivo.

Questo è intrinsicamente thread compatibile poiché si utilizza una coda. Tuttavia, vorresti comunque mettere una certa protezione di tipo mutex attorno alla scrittura in coda in modo che un dato registro < < "stuff" < < "more stuff"; l'operazione di tipo rimane line-atomic.

Buon divertimento!

+0

Un mutex non significa che se un thread sta già tentando di scrivere, dovrebbe girare fino a quando non è stato sbloccato? In che modo questo aiuta? – Electro

+0

Non ritarderei di certo la conversione dell'oggetto nel flusso. Metterlo in un altro thread significa doverlo sincronizzare ... ed è probabile che faccia male come un matto. –

+0

@Electro - non girare, ma bloccare. Ma se non stai facendo l'elaborazione delle stringhe, è un intervallo MOLTO breve per caricare la coda. L'elaborazione della stringa viene eseguita dal thread di registrazione. @Matthieu, eseguendo l'elaborazione delle stringhe in tempo reale fa molto più male di qualsiasi blocco mutex durante il caricamento di una coda. –

0

Penso che l'approccio corretto non sia one-file-per-thread, ma one-thread-per-file. Se un solo file (o una risorsa in generale) nel tuo sistema è accessibile solo da un thread, la programmazione thread-safe diventa molto più semplice.

Quindi, perché non rendere Logger un thread dedicato (o più thread, uno per file, se si registrano elementi diversi in file diversi) e in tutti gli altri thread, scrivere in log posizionerà il messaggio nella coda di input nel thread del Logger appropriato, che otterrà dopo aver finito di scrivere il messaggio precedente. Tutto ciò che serve è un mutex per proteggere la coda dall'aggiunta di un evento mentre Logger sta leggendo un evento e un condvar per il Logger da attendere quando la sua coda è vuota.

+0

È possibile allontanarsi senza utilizzare un mutex con una coda senza blocco. La variabile condizionale è molto più diversa però. A seconda della carica, potresti preferire la rotazione piuttosto che andare a dormire e svegliarti più tardi. Dipende anche dal fatto che tu abbia o meno un core inattivo :) –

+0

Se qualcosa di occupato attende nel nostro sistema, il watchdog ucciderà l'intera applicazione :) – Cubbi

1

Avete considerato l'utilizzo di una libreria di registro.

Sono disponibili diversi, ho scoperto Pantheios di recente e sembra davvero incredibile.

È più un logger front-end, è possibile personalizzare il sistema utilizzato. Può interagire con ACE o log4cxx per esempio e sembra davvero facile da usare e configurare. Il vantaggio principale è che usa operatori tipizzati, che è sempre ottimo.

Se si desidera solo una libreria di registrazione barebone:

  • ACE
  • log4c *
  • Boost.Log

sbizzarrirvi :)

Vorrei sottolineare che si tratta di possibile implementare code senza blocco in C++ e che sono grandi per la registrazione.

+0

Hm, non penso di voler introdurre nessuno di questi.Le prime due sembrano eccessive, e quest'ultima ha avuto molti problemi di prestazioni nella sua recensione, che è stata una delle ragioni per cui non l'hanno aggiunta alla collezione Boost propriamente detta. – Electro

17

Ho notato questo thread di 1 anno + vecchio. Forse il logger asincrono che ho scritto potrebbe essere interessante.

http://www.codeproject.com/KB/library/g2log.aspx

G2log utilizza una coda di messaggi protetti per inoltrare voci di log ad un lavoratore di fondo che il disco lento accessi.

L'ho provato con una coda senza blocco che ha aumentato il tempo medio per una chiamata LOG ma ha diminuito il tempo peggiore, tuttavia sto utilizzando la coda protetta ora poiché è multipiattaforma. È testato su Windows/Visual Studio 2010 e Ubuntu 11.10/gcc4.6.

È rilasciato come dominio pubblico in modo che tu possa farne ciò che vuoi senza stringhe.

+0

La solita cosa che faccio se il logging non deve portare a nessun blocco (es. Debugging race conditions with prints .. hey funziona ed è semplice!) Usa una coda di messaggi locale thread che memorizza i token con timestamp (bene in questo caso probabilmente meglio produrlo direttamente con IO asincrono). Se hai bisogno dei dati, devi solo ordinare l'output in seguito ed è piuttosto ingombrante per la registrazione generale, ma ha la quantità di sincronizzazione più bassa possibile: nil. – Voo

+0

Ciò che è importante, ovviamente, non è solo la sicurezza del thread e il blocco minimo, ma anche assicurarsi che le voci del registro siano archiviate in caso di crash del software (errore di segmentazione, errore in virgola mobile ecc.). G2log prevede che utilizzando un gestore di segnale, in caso di "segnale fatale", scarica le voci in coda nel file prima che il segnale continui (e interrompa il programma) –

+0

@ KjellHedström - seguire i passaggi in questo link http: // stackoverflow. it/help/user-merge per riunire i tuoi account. – ChrisF

0

Ho avuto lo stesso problema e credo di aver trovato la soluzione perfetta. Vi presento una libreria single-header denominata loguru: https://github.com/emilk/loguru

È semplice da usare, portatile, configurabile, basata su macro e di default non contiene #include (per quei tempi di compilazione dolci e dolci).

Problemi correlati