c#中最有效的从Queue中取出字节的方法

本文关键字:方法 字节 有效 Queue | 更新日期: 2023-09-27 18:14:01

我有一个队列与一些数据。如果我想检索5个字节(或者如果小于5个字节,则尽可能多地检索),以下哪种方法更有效,或者没有区别?

选项1:

        byte[] ret = null;
        if (this.dataQueue.Count >= numBytes)
        {
            ret = new byte[numBytes];
        }
        else
        {
            ret = new byte[this.dataQueue.Count];
        }
        for (int i = 0; i < ret.Length; i++)
        {
            ret[i] = this.dataQueue.Dequeue();
        }
        return ret;

选项2:

        List<byte> l = new List<byte>();
        try
        {
            for (int i = 0; i < numBytes; i++)
            {
                l.Add(this.dataQueue.Dequeue());
            }
        }
        catch
        {
            System.Diagnostics.Debug.WriteLine(string.Format("Unable to retrieve requested number of bytes from queue. ({0} bytes requested, {1} bytes available)", numBytes, l.Count));
        }
        return l.ToArray();

提前感谢您的建议

c#中最有效的从Queue中取出字节的方法

性能确实取决于你的场景,并且总是有人会警告你不要过早优化,并在假设某些东西很慢之前找到瓶颈等等,然后还有来自角度的假设可能成立也可能不成立;我确实同意前一部分,但不喜欢妄下结论,并认为程序的部分被证明是较慢的,因此呼吁需要对这些部分进行优化。

无论如何,考虑以下基本的,不完全实用的特别程序(使用您的方法,这里称为DequeueTryDequeue,但没有列出):

var data = new byte[4096];
var random = new Random();      
var queue = new Queue<byte>();
var stopWatch = new Stopwatch();
TimeSpan dequeueTimespan, tryDequeueTimespan;
stopWatch.Restart();
for (int i = 0; i < 1000000; i++)
{
    random.NextBytes(data);
    foreach (var item in data)
    {
        queue.Enqueue(item);
    }
    Dequeue(queue, 1024);
    queue.Clear();
}
stopWatch.Stop();
dequeueTimespan = stopWatch.Elapsed;
stopWatch.Restart();
for (int i = 0; i < 1000000; i++)
{
    random.NextBytes(data);
    foreach (var item in data)
    {
        queue.Enqueue(item);
    }
    TryDequeue(queue, 1024);
    queue.Clear();
}
stopWatch.Stop();
tryDequeueTimespan = stopWatch.Elapsed;
Console.WriteLine("Dequeue:    {0}", dequeueTimespan);
Console.WriteLine("TryDequeue: {0}", tryDequeueTimespan);
Console.ReadKey();

现在,如果我们对每个函数运行10000次迭代,我们得到:

Dequeue:    00:00:12.6178244
TryDequeue: 00:00:13.6747715

对于每个方法的1000000次迭代:

Dequeue:    00:02:16.4144764
TryDequeue: 00:02:13.2039597

诚然,我们在这里做着其他工作,但这都是相对的;我们在这里也夸大了你的情况,因为你只需要5个字节,所以…

在10000次迭代的第一个例子中:

Dequeue:    00:00:10.5624014
TryDequeue: 00:00:10.2529997
我不是说这些是完美的结果,但它们结果;但重点是。

两者之间的性能下降可以忽略不计。

在实际环境中还有许多其他因素需要考虑,不必说,这里也不试图列出所有的变量,您将会(或将会)意识到这些因素,并且应该花时间将它们与您的场景联系起来。

别误会,你问的是一个几乎不可能的问题。当处理如此微小的差异时,你需要更多的信息来做出裁决。

例如,正在进行哪些优化,以及将在哪个体系结构上运行。此外,当前程序的状态如何?流(内存紧吗?CPU的工作速度接近100%吗?),缓存(application 'OS'hardware)呢?

这个列表是不完整的,离它还很远,但它应该通过点-如果你在一个精确的尺度上进行优化和性能,你将需要更多的细节(不仅对我们,而且对任何可能有答案的人)。

如果你能详细说明你的问题,那就太好了。

编辑:

请注意,这两个方法以相同的方式(调用dequeue()的for循环)将Queue从队列中取出,因此在这方面并没有什么不同,不同之处在于它们从Queue中取出项目的方式。如果问题是最快的方法是什么(使用脱离队列的项目),那就是不要收集它们并将它们发送到它们的流中。如果这些项是要返回的,那么您可以回到最初的问题,但附带一个可能对您有所帮助的子问题—在这些项的集合退出队列后,您希望对它们做些什么?

希望能有所帮助

第一个,因为它只分配一次,而

l.Add(this.dataQueue.Dequeue()) 

需要重新分配list所需的空间几次,除非您预先预留了它:

l.Capacity = 5

不影响列表的长度,它只是为元素保留内存空间(我们知道你最多有5个)。

当然,如果你真的需要在队列中有字节并且每次需要获取一个字节时调用Dequeue也是值得检查的。