我有以下内容:
生产者不时会发疯,只能很快产生一种'那种',然后恢复正常。 例如:6666666666666666666666666666666666666666666666675444696,1秒钟。
我的目标是尽可能降低不同类型的数字。 比如,在上一个示例中 我有:
如果我使用简单的FIFO算法,我会在所有'6'被消耗之前等待很长时间。我宁愿“优先”其他数字,然后消耗'6'。
这样的算法是否已经存在? (C#实施是一个加号)
目前,我正在考虑这个算法:
为每个队列依次出列一个项目:
private int _currentQueueId;
private Queue<T>[] _allQueues;
public T GetNextItemToConsume<T>()
{
//We assume that there is at least one item to consume, and no lock needed
var found = false;
while(!found)
{
var nextQueue = _allQueues[_currentQueueId++ % 10];
if(nextQueue.Count > 0)
return nextQueue.DeQueue();
}
}
你有比这更好的算法吗? (或任何想法)
NB1:我在消费过程中没有领先(也就是说我不能提高消费速度和消费线程的数量......)(实际上无限的消费速度会解决我的问题)< / p>NB2:确切时间的数字不相关,但我们可以假设消费量比生产快十倍
NB3:我对制作人的'疯狂'行为没有领先,事实上这是正常的(但不是那么频繁)制作行为
答案 0 :(得分:0)
以上是一个比上述评论更完整的例子:
sealed class Item {
public Item(int group) {
ItemGroup = group;
}
public int ItemGroup { get; private set; }
}
Item TakeNextItem(IList<Item> items) {
const int LowerBurstLimit = 1;
if (items == null)
throw new ArgumentNullException("items");
if (items.Count == 0)
return null;
var item = items.GroupBy(x => x.ItemGroup)
.OrderBy(x => Math.Max(LowerBurstLimit, x.Count()))
.First()
.First();
items.Remove(item);
return item;
}
我的想法是根据频率对项目进行排序,然后从频率最低的项目中选择。它与您的多个队列的想法相同,但它是即时计算的。 如果有多个具有相同频率的组,则将采用最旧的项目。 (假设GroupBy和OrderBy是稳定的。它们在实践中,但我不确定它是否在文档中说明)
如果要按时间顺序处理项目,请增加LowerBurstLimit
,但队列中的项目超过LowerBurstLimit
的项目除外。
测量我在LinqPad中创建此快速代码的时间 (Eric Lippert:请忽略这一部分: - ))
void Main()
{
var rand = new Random();
var items = Enumerable.Range(1, 1000)
.Select(x => { // simulate burst
int group = rand.Next(100);
return new Item(group < 90 ? 1 : (group % 10));
})
.ToList();
var first = TakeNextItem(items); // JIT
var sw = new Stopwatch();
sw.Start();
while (TakeNextItem(items) != null) {
}
sw.Stop();
Console.WriteLine("Elapsed: {0} ms", sw.ElapsedMilliseconds);
}
当我使用1000个项目运行此代码时,我的3岁笔记本电脑需要大约80毫秒。即每个“Take”平均80μs。
GroupBy应为O(N * M),OrderBy O(M * LogM)和删除O(N)(N =平均队列长度,M =组数),因此性能应与N线性比例。即a 10000个项目队列每个“Take”需要~800μs(我在测试中得到了700μs,10000个项目)
答案 1 :(得分:0)
我将使用你提到的10个队列,并根据特定队列中存在的元素数量选择从中统计出队的队列。具有最多元素的队列更有可能被选择用于出队。
为了获得更好的性能,您需要跟踪所有队列中元素的总数。对于每个出列操作,在0和总计数-1之间绘制一个随机的int X,这将告诉你从哪个队列出队(循环遍历队列,从X中减去队列中元素的数量,直到你低于零) ,然后选择那个队列。)