在C#中从队列中出队字节的最有效方法

时间:2011-11-09 11:02:30

标签: c# list queue

我有一个包含一些数据的队列。如果我想检索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();

提前感谢任何建议。

3 个答案:

答案 0 :(得分:1)

性能实际上取决于您的场景,并且总是有人会警告您不要过早优化并在假设某些事情变得缓慢之前找到瓶颈,然后还有可能或可能的角度推测不成立;我真的与前一部分保持一致,但不喜欢跳到结论,并认为程序的各个部分被证明是较慢的,因此需要对部分进行优化等。

有了这个,无论如何,请考虑以下原始的,不完全实用的临时程序(使用您的方法,在此处命名为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

我不是说这些是完美的结果,但它们结果;但重点是这一点。

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

在实际环境中还有许多其他因素需要考虑,不用说,不要试图在这里列出所有的变化,你将(或变得)意识到并且应该花时间与你的场景。

答案 1 :(得分:0)

第一个,因为它分配1个,而

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

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

l.Capacity = 5

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

当然,每次需要获取一个字节时,还需要检查是否确实需要队列中的字节并调用Dequeue。

答案 2 :(得分:0)

不要采取错误的方式,但你问的是一个几乎不可能的问题。在处理这么小的差异时,你需要更多的信息来做出任何一种裁决。

例如,有哪些优化措施,以及将要运行的架构。 而且,目前的节目状态是什么?流量(内存紧张?CPU工作在100%左右?),缓存(应用\ OS \硬件)怎么样。

这个列表不完整,远不是它,但它应该超越这一点 - 如果你在精确定位的规模上进行优化和性能,你将需要更多的细节(不仅仅是我们,但对于那些可能有想法回答的人来说。)

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

编辑:

请注意,这两种方法以相同的方式对队列进行队列化(带有对Dequeue()的调用的for循环),因此在这方面没有什么不同,而是他们收集从队列中出队的项目的方式。队列。如果问题是最快的方法(使用出列物品),那就不是收集它们并将它们发送到它们的流程中。如果要返回这些项目,那么您将回到原始问题,但是有一个可能对您有帮助的子问题 - 您希望在它们出列后对项目集合做什么。

希望这有帮助

相关问题