2010-07-18 1 views
11

Ich versuche zu ersetzen, was ich normalerweise als Ringpuffer + implementieren würde. Die Funktion der Warteschlange besteht darin, ankommende Bytes (z. B. vom seriellen Port oder einem anderen Datenstrom) zu puffern, während ein Parser Bytes in der Warteschlange untersucht und Nachrichtenpakete erkennt und extrahiert.Effiziente C# -Byte-Warteschlange zum Parsing von Bytestreams für binäre Nachrichtenpakete

Kriterien:

  • wachsen kann (dh nicht feste Größe)
  • = 1 Byte einer Warteschlange eingereiht

  • = 1 Byte sein kann, zu einer Zeit sein kann zu einer Zeit aus der Warteschlange

  • effiziente

Ich bin nur

zu verwenden versucht
System.Collections.Generic.Queue<byte> 

... aber ich bin nicht sicher, ob dies die effizienteste Art zu verwenden ist. Irgendwelche Vorschläge?

Gibt es intelligentere Möglichkeiten, das zu tun, was ich versuche? (ZB. Interessante Vorschläge here)

Danke für Ihre Vorschläge & Eingabe.

Prembo.

Antwort

1

Queue<byte> wird von einem byte[] gesichert, aber Sie würden eine bessere Leistung sehen, ob zu/von dem zugrunde liegenden Puffer kopiert Array.Copy mit eher als Schleife durch Enqueue/Dequeue Methoden. Wenn also Queue<byte> Ihnen nicht die gewünschte Leistung bietet, können Sie möglicherweise eine eigene Queue-Klasse implementieren, die QueueMultiple- und DequeueMultiple-Methoden bereitstellt.

3

Nun, Queue<byte> wird in Bezug auf Speicher effizient sein. Es wird im Grunde ein byte[] hinter den Kulissen sein. Es kann etwas umständlich sein, wenn Sie ganze Blöcke gleichzeitig aus der Warteschlange entfernen oder in die Warteschlange stellen möchten. Jede Operation sollte für ein einzelnes Byte O (1) amortisiert werden, was dazu führt, dass O (n) einen Block der Größe n ... in die Warteschlange einfügt oder aus der Warteschlange nimmt ... aber der Skalierungsfaktor ist höher als eine Pufferblockkopie.

2

Abhängig davon, wie die eingehenden Bytes empfangen werden und wie der Parser sie untersucht, können Sie eine Queue<byte[]> in Betracht ziehen.

1

Ich weiß, ich bin nicht hilfreich, aber Sie können eine Ihrer eigenen schreiben.
Der theoretische Teil:
Die Warteschlange sollte

 
0             n 
|----------------------------------------------------| 
       |      | 
       head      tail 

Jedesmal, wenn Sie k Bytes hinzufügen müssen für Schwanz in byte[] und 2 Indizes, 1 für Kopf und 1 liegen Sie Schwanz k Einheiten nach links bewegen und die in setzen Der neue Space hat dort Daten angelegt.

 
0             n 
|-------------------------------new data-------------| 
       |    |  | 
       head   new tail old tail 

Jedes Mal, wenn Sie k Bytes Pop benötigen bewegen Sie den Kopf k Einheiten links und nehmen Daten aus dem Raum verloren.

Wenn Kopf und Heck kollidieren, müssen Sie die Größe des Containers verdoppeln und jede Hälfte auf die neue kopieren.

Denken Sie daran: Wenn Sie 1234 hinzufügen und dann 2 Buchstaben Pop erhalten Sie 34

(ich weiß nicht, ob ich diesen Beitrag als Community Wiki markieren sollte)

+0

Generell Menschen markieren nicht ihre Antworten als Community Wiki. Wenn es sich bei der Frage um ein Community-Wiki handelt, werden die Antworten auch Community-Wiki sein. –

+0

Ich glaube, ich verstehe nicht, was Gemeinschaft Wiki ist. – Dani

1

Hier an efficient implementation von einen Puffer ich vor einer Weile geschrieben:

  • Resizeable: so dass Daten in die Warteschlange einzureihen und nicht Pufferüberlauf Ausnahme auslösen;
  • Effiziente: verwendet einen einzelnen Puffer und Buffer.Copy Operationen/dequeue Daten einzureihen