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();
提前感谢您的建议
性能确实取决于你的场景,并且总是有人会警告你不要过早优化,并在假设某些东西很慢之前找到瓶颈等等,然后还有来自角度的假设可能成立也可能不成立;我确实同意前一部分,但不喜欢妄下结论,并认为程序的部分被证明是较慢的,因此呼吁需要对这些部分进行优化。
无论如何,考虑以下基本的,不完全实用的特别程序(使用您的方法,这里称为Dequeue
和TryDequeue
,但没有列出):
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也是值得检查的。