2012-11-30 34 views
7

Sfondodecodifica efficiente di strutture di testo e binari (pacchetti)

V'è uno strumento ben noto chiamato Wireshark. Lo sto usando da anni. È grandioso, ma le prestazioni sono il problema. Lo scenario di utilizzo comune include diverse fasi di preparazione dei dati al fine di estrarre un sottoinsieme di dati da analizzare in seguito. Senza quel passo ci vogliono pochi minuti per filtrare (con grandi tracce Wireshark è quasi inutilizzabile).

enter image description here

L'idea attuale è quella di creare una soluzione migliore, veloce, parallela ed efficiente, da utilizzare come dati aggregatore/memorizzazione.

Requisiti

Il requisito reale è quello di utilizzare tutta la potenza fornita da hardware moderno. Dovrei dire che c'è una stanza per diversi tipi di ottimizzazione e spero di aver fatto un buon lavoro negli strati superiori, ma la tecnologia è la domanda principale in questo momento. Secondo il disegno attuale ci sono vari gusti di decodificatori a pacchetto (dissettori):

  • decoder interattivi: logica di decodifica può essere facilmente modificata in runtime. Tale approccio può essere piuttosto utile per gli sviluppatori di protocolli: la velocità di decodifica non è così importante, ma la flessibilità e risultati rapidi sono più importanti
  • decodificatori incorporabili: può essere utilizzato come libreria. Questo tipo dovrebbe avere buone prestazioni e essere abbastanza flessibile da utilizzare tutte le CPU e i core disponibili
  • decodificatori come servizio: è possibile accedere tramite un'API pulita. Questo tipo dovrebbe fornire la migliore delle prestazioni e dell'efficienza razza

Risultati

mia soluzione attuale è decoder JVM-based. L'idea reale è di riutilizzare il codice, eliminare il porting, ecc., Ma avere comunque una buona efficienza.

  • decoder interattivi: attuate in Groovy
  • decoder Embeddabili: implementato su Java
  • decodificatori come servizio: Tomcat + ottimizzazioni + decoder embeddable avvolti in un servlet (binari in XML out)

Problemi da risolvere

  • Groovy offre modo di tanto potere e tutto, ma Lucks espressività in questo caso particolare
  • protocollo di decodifica in una struttura ad albero è un vicolo cieco - troppe risorse sono semplicemente sprecati
  • Il consumo di memoria è un po ' difficile da controllare.Ho fatto ottimizzazioni diverse, ma ancora non è felice con profilatura risultati
  • Tomcat con varie campane e fischietti ancora presenta molto luminosa (soprattutto la gestione di connessione)

sto facendo destra con JVM ovunque? Vedi qualche altro modo valido ed elegante per raggiungere l'obiettivo iniziale: ottenere decodificatori di protocollo altamente scalabili ed efficienti facili da scrivere?

Il protocollo, il formato dei risultati, ecc. Non sono corretti.

+1

Puoi restringere la tua domanda? Questo è incredibilmente aperto. Non so davvero che tipo di risposte stai cercando. –

+0

Sono d'accordo con @JohnKugelman, questa potrebbe essere una bella domanda, ma come affermato è troppo ampia. Vorrei provare a rimuovere il più possibile e cercare di mantenere le informazioni pertinenti a ciò che stai veramente chiedendo (sui frame del protocollo di decodifica). Trascorri 4 paragaphs e 2 elenchi puntati parlando di cose extra e solo 1 frase con la tua vera domanda. – durron597

+0

Ho modificato la domanda fornendo dettagli preziosi e rimuovendo alcune altre cose. Non esiste una sola soluzione. Potrebbero essere proposte molte o forse molte risposte preziose, fornendo spunti interessanti, descrivendo tecniche inusuali e mettendo in luce buone soluzioni architettoniche. –

risposta

7

ho trovato diversi miglioramenti possibili:

decoder interattivi

espressività Groovy può essere notevolmente migliorata, estendendo sintassi Groovy usando AST Transformations. Pertanto, sarebbe possibile semplificare la creazione di decoder che offrono ancora buone prestazioni. AST (acronimo di Abstract Syntax Tree) è una tecnica in fase di compilazione.

Quando il compilatore Groovy compila script Groovy e classi, ad un certo punto del processo, il codice sorgente finirà per essere rappresentato in memoria sotto forma di un albero sintattico cemento, poi trasformato in astratta Albero della sintassi. Lo scopo di AST Transformations è quello di consentire agli sviluppatori di di collegarsi al processo di compilazione per poter modificare l'AST prima di trasformarlo in bytecode che verrà eseguito dalla JVM.

Non voglio reinventare la rotellina introducendo un altro linguaggio per definire/descrivere una struttura di protocollo (è sufficiente avere ASN.1).L'idea è di semplificare lo sviluppo dei decodificatori al fine di fornire una tecnica di prototipazione rapida. Fondamentalmente, verrà introdotta una sorta di DSL.

Further reading

decoder Embeddabili

Java possono introdurre qualche ulteriore sovraccarico. Ci sono diverse librerie per affrontare tale questione:

enter image description here

Francamente non vedo alcuna altra opzione ad eccezione di Java per th è strato.

decodificatori come servizio

No Java è necessario su questo livello. Finalmente ho una buona opzione per andare ma il prezzo è piuttosto alto. GWan sembra davvero buono.

enter image description here

Alcuni porting supplementare sarà richiesto, ma è sicuramente la pena.

3

Questo problema sembra condividere le stesse caratteristiche di molti problemi di implementazione I/O ad alte prestazioni, ovvero il numero di copie di memoria domina le prestazioni. I modelli di interfaccia scatter-gather per l'I/O asincrono seguono questo principio. Con scatter-gather, i blocchi di memoria vengono attivati ​​sul posto. Finché i decodificatori del protocollo accettano flussi di blocchi come input anziché come flussi di byte, avrai eliminato un sacco di overhead delle prestazioni dello spostamento della memoria per preservare l'astrazione del flusso di byte. Il flusso di byte è un'astrazione molto buona per risparmiare tempo di progettazione, ma non così bene per I/O ad alte prestazioni.

In un problema correlato, farei attenzione alla JVM solo per il tipo base String. Non posso dire di avere familiarità con il modo in cui lo String è implementato nella JVM, ma immagino che non ci sia un modo per creare una stringa da una lista di blocchi senza fare una copia di memoria. D'altra parte, un tipo nativo di stringa che potrebbe e che interagisce con JVM String compatibilmente potrebbe essere un modo per dividere la differenza.


L'altro aspetto di questo problema che sembra rilevante è quello dei linguaggi formali. Nello spirito di non copiare blocchi di memoria, non si desidera eseguire la scansione dello stesso blocco di memoria più e più volte. Dal momento che si desidera apportare modifiche in fase di esecuzione, ciò significa che probabilmente non si desidera utilizzare una macchina di stato precompilata, ma piuttosto un parser di discesa ricorsiva che può essere inviato a un interprete di protocollo appropriato a ogni livello di discesa. Ci sono alcune complicazioni quando uno strato esterno non specifica il tipo di uno strato interno. Quelle complicazioni sono peggiori quando non si ottiene nemmeno la lunghezza del contenuto interiore, dal momento che si sta facendo affidamento sul contenuto interiore per essere ben formato per prevenire il fuggiasco. Tuttavia, vale la pena di prestare attenzione per capire quante volte verrà scansionato un singolo blocco.

+0

Le stringhe sono spesso, ma non sempre, internate in una piscina di lunga durata. Le stringhe possono essere pre-combinate con StringBuilder (http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html). – claj

1

Il traffico di rete è in aumento (some analytics), quindi sarà necessario elaborare sempre più dati al secondo.

L'unico modo per ottenere ciò è utilizzare più potenza della CPU, ma la frequenza della CPU è stabile. Sta crescendo solo il numero di core. Sembra che l'unico modo sia utilizzare i core disponibili in modo più efficiente e scalare meglio.

enter image description here

Problemi correlati