Эффективная байтовая очередь C # для анализа потока байтов для пакетов двоичных сообщений - PullRequest
11 голосов
/ 18 июля 2010

Я пытаюсь заменить то, что я обычно реализую как круговой буфер +. Функция очереди состоит в том, чтобы буферизовать входящие байты (например, из последовательного порта или некоторого другого потока данных), в то время как анализатор анализирует байты в очереди, обнаруживает и извлекает пакеты сообщений.

Критерии:

  • может расти (т.е. не фиксированного размера)
  • = 1 байт можно ставить в очередь за раз

  • = 1 байт может быть снят с очереди одновременно

  • эффективный

Я испытываю желание просто использовать

System.Collections.Generic.Queue<byte>

... но я не уверен, что это самый эффективный тип для использования. Есть предложения?

Есть ли более разумные способы делать то, что я пытаюсь сделать? (Например, интересные предложения здесь )

Спасибо за ваши предложения и вклад.

Prembo.

Ответы [ 5 ]

3 голосов
/ 18 июля 2010

Ну, Queue<byte> будет эффективным с точки зрения памяти.В основном это будет byte[] за кулисами.Это может быть немного неловко, если вы хотите убрать или поставить в очередь целые куски одновременно.Каждая операция должна амортизироваться O (1) для одного байта, что приводит к тому, что O (n) ставит в очередь или удаляет из очереди фрагмент размером n ... но коэффициент масштабирования будет выше, чем, скажем, копия буферного блока.

2 голосов
/ 19 июля 2010

Я знаю, что я не помогу, но вы можете написать свой собственный.
Теоретическая часть:
Очередь должна быть в byte[] и 2 индекса, 1 для головы и 1 для хвоста

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

Каждый раз, когда вам нужно добавить k байт, вы перемещаете хвост на 1008 * единиц влево и помещаете туда данные, созданные в новом пространстве.

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

Каждый раз, когда вам нужно выдвинуть k байтов, вы перемещаете голову k единиц влево и извлекаете данные из потерянного пространства.

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

В случае столкновения головы и хвоставам нужно удвоить размер контейнера и скопировать каждую половину в новый.

Имейте в виду: если вы добавите 1234, а затем выскочит 2 буквы, вы получите 34

(не знаю, стоит ли отмечать этот пост как вики сообщества)

2 голосов
/ 18 июля 2010

В зависимости от того, как принимаются входящие байты и как их анализирует анализатор, вы можете рассмотреть Queue<byte[]>.

2 голосов
/ 18 июля 2010

Queue<byte> поддерживается byte[], но вы увидите лучшую производительность, если копируете в / из нижележащего буфера, используя Array.Copy, а не зацикливаетесь на методах постановки / удаления.Так что лично, если Queue<byte> не дает нужной вам производительности, вы можете реализовать свой собственный класс очереди, который предоставляет методы QueueMultiple и DequeueMultiple.

1 голос
/ 18 апреля 2014

Вот эффективная реализация буфера, который я написал недавно:

  • Resizeable : разрешить помещать в очередь данные и не генерировать исключение переполнения буфера;
  • Эффективный : использует один буфер и операции Buffer.Copy для постановки / удаления данных из очереди
...