用于解析二进制消息包的字节流的高效 C# 字节队列

发布于 2024-09-10 12:29:19 字数 556 浏览 7 评论 0原文

我正在尝试替换我通常实现的循环缓冲区+。队列的功能是缓冲传入的字节(例如,来自串行端口或其他一些数据流),同时解析器检查队列中的字节并检测和提取消息包。

标准:

  • 可以增长(即不固定大小)
  • <块引用>

    = 一次可以入队 1 个字节

  • <块引用>

    = 一次可以出列 1 个字节

  • 有效地

出列我很想使用

System.Collections.Generic.Queue<byte>

...但我不确定这是否是最有效的类型。有什么建议吗?

有没有更聪明的方法来做我想做的事情? (例如,有趣的建议此处

感谢您的建议&输入。

普雷姆博。

I'm trying to replace what I would usually implement as a circular-buffer+. The function of the queue is to buffer incoming bytes (eg. from serial port or some other stream of data), whilst a parser examines bytes in the queue and detects and extracts message packets.

Criteria:

  • can grow (ie not fixed-sized)
  • = 1 bytes can be enqueued at a time

  • = 1 bytes can be dequeued at a time

  • efficient

I'm tempted just to use

System.Collections.Generic.Queue<byte>

... but I'm not sure if this is the most efficient type to use. Any suggestions?

Are there any smarter ways of doing what I'm trying to do? (Eg. Interesting suggestions here)

Thanks for your suggestions & input.

Prembo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

開玄 2024-09-17 12:29:19

嗯,Queue 在内存方面会非常高效。它基本上是幕后的一个byte[]。不过,如果您想一次将整个块出队或入队,那么使用起来可能会有点尴尬。对于单个字节,每个操作应分摊为 O(1),导致 O(n) 入队或出队大小为 n 的块...但缩放因子将高于(例如)缓冲区块副本。

Well, Queue<byte> will be efficient in terms of memory. It will basically be a byte[] behind the scenes. It may be slightly awkward to work with if you want to dequeue or enqueue whole chunks at a time though. Each operation should be amortized O(1) for a single byte, leading to O(n) to enqueue or dequeue a chunk of size n... but the scaling factor will be higher than (say) a buffer block copy.

戒ㄋ 2024-09-17 12:29:19

Queuebyte[] 支持,但如果使用 Array.Copy 复制到底层缓冲区或从底层缓冲区复制,您会看到更好的性能> 而不是通过入队/出队方法循环。因此,就个人而言,如果 Queue无法为您提供所需的性能,那么您可以实现自己的队列类,该类提供 QueueMultiple 和 DequeueMultiple 方法。

Queue<byte> is backed by a byte[], but you would see better performance if copying to/from the underlying buffer using Array.Copy rather than looping through Enqueue/Dequeue methods. So personally, if Queue<byte> doesn't give you the performance you want, then you might implement your own queue class that provides QueueMultiple and DequeueMultiple methods.

过去的过去 2024-09-17 12:29:19

根据传入字节的接收方式以及解析器检查它们的方式,您可能会考虑使用 Queue

Depending upon how the incoming bytes are received and how the parser examines them, you might consider a Queue<byte[]>.

梨涡少年 2024-09-17 12:29:19

我知道我帮不上忙,但你可以自己写一个。
理论部分:
队列应该位于 byte[] 和 2 个索引中,1 个用于头部,1 个用于尾部

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

每次需要添加 k 字节时,您都会移动尾部 k 剩下的单位并将创建的数据放入新空间中。

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

每次需要弹出 k 字节时,您需要将头向左移动 k 个单位,并从丢失的空间中获取数据。

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

如果头部和尾部发生碰撞,则需要将容器的大小加倍,并将每一半复制到新的容器中。

请记住:如果您添加 1234 然后弹出 2 个字母,您将得到 34

(我不知道是否应该将此帖子标记为社区 wiki)

I know I'm not be helpful, but you can write one of your own.
The theoretic part:
The queue should be in byte[] and 2 indexes, 1 for head and 1 for tail

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

Each time you need to add k bytes you move tail k units left and put the in the new space created data there.

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

Each time you need to pop k bytes you move head k units left and take data from the space lost.

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

In case head and tail collide, you need to double the size of the container and copy each half to the new one.

Keep in mind: if you add 1234 and then pop 2 letters you will get 34

(I don't know if I should mark this post as community wiki)

夏末的微笑 2024-09-17 12:29:19

这是一个高效的实现我之前写的一个缓冲区:

  • 可调整大小:允许对数据进行排队并且不会抛出缓冲区溢出异常;
  • 高效:使用单个缓冲区和 Buffer.Copy 操作将数据入队/出队

Here's an efficient implementation of a buffer I wrote a while ago:

  • Resizeable: allowing to queue up data and not throw buffer overflow exception;
  • Efficient: uses a single buffer and Buffer.Copy operations to enqueue/dequeue data
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文