我需要执行strategy.AllTablesUpdated();
在 2 毫秒内执行 50 个策略(我需要每秒重复大约 500 次)。
使用下面的代码我发现只是 Monitor.TryEnter
通话时间长达 1 毫秒(!!!),我这样做了 50 次!
// must be called ~500 times per second
public void FinishUpdatingTables()
{
foreach (Strategy strategy in strategies) // about ~50, should be executed in 2 ms
{
// this slow and can be paralleled
strategy.AllTablesUpdated();
}
}
......................
public override bool AllTablesUpdated(Stopwatch sw)
{
this.sw = sw;
Checkpoint(this + " TryEnter attempt ");
if (Monitor.TryEnter(desiredOrdersBuy))
{
Checkpoint(this + " TryEnter success ");
try
{
OnAllTablesUpdated();
} finally
{
Monitor.Exit(desiredOrdersBuy);
}
return true;
} else
{
Checkpoint(this + " TryEnter failed ");
}
return false;
}
public void Checkpoint(string message)
{
if (sw == null)
{
return;
}
long time = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
Log.Push(LogItemType.Debug, message + time);
}
从日志(以微秒为单位)来看,失败的尝试花费了约 1 毫秒:
block 引用>12:55:43:778 Debug: TryEnter attempt 1264 12:55:43:779 Debug: TryEnter failed 2123
从日志(以微秒为单位)来看,成功尝试花费了约 0.01 毫秒:
block 引用>12:55:49:701 Debug: TryEnter attempt 889 12:55:49:701 Debug: TryEnter success 900
所以现在我认为
Monitor.TryEnter
50 个策略一一执行对我来说太昂贵了。所以我想使用Task
来并行这项工作像这样:// must be called ~500 times per second public void FinishUpdatingTables() { foreach (Strategy strategy in strategies) // about ~50, should be executed in 2 ms { // this slow and can be paralleled Task.Factory.StartNew(() => { strategy.AllTablesUpdated(); }); } }
我也可能会替换
Monitor.TryEnter
到只是lock
与这种方法一样,一切都将是异步的。我的问题:
- 为什么
Monitor.TryEnter
这么慢吗? (如果未获得锁,则为 1 毫秒)- 从 50 开始就好了
Task
每 2 毫秒 = 每秒 25 000 个任务? .NET 可以有效地管理这个问题吗?我还可以使用BlockingCollection
的生产者-消费者模式并仅启动 50 个“workers”一次,然后每 2 毫秒向 BlockingCollection 提交新的 50 个项目包?这样会更好吗?- 如何执行每 2 毫秒并行的 50 个方法(每秒 500 次),总共每秒 25,000 次?
最佳答案
- Monitor.TryEnter(object) 只是 Monitor.TryEnter(object, 0, ref false) (0 毫秒超时)。如果没有获得锁,那 1 毫秒只是尝试获取锁的开销。
- 您可以启动任意数量的任务,它们都使用线程池,但线程池的最大数量受到限制。最大值取决于您的系统、核心数量、内存等...但可以肯定的是,它不会是 25,000 个线程。然而,如果您开始干预 TPL 调度程序,您就会遇到麻烦。我只是使用
Parallel.Foreach
并看看它能让我走多远。 Parallel.ForEach
。我还要确保strategies
的类型为IList
,以便在不等待迭代器的情况下触发尽可能多的项目。
您尚未将代码粘贴到 OnAllTablesUpdated(),您在该过程期间保持锁定。这将成为你所有可能性的瓶颈。
一些问题,为什么当表准备好处理时使用锁?
- 委托(delegate)是不可能的吗?
- 为什么在运行策略时锁定它?您是否正在修改每个策略中的该表?如果是这样的话,你能不复印一下吗?
关于c# - 如何有效地每秒执行50个并行方法500次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10206624/