我需要在2 ms内执行strategy.AllTablesUpdated();
50个策略(我需要重复每秒500次)。
使用下面的代码,我发现只有Monitor.TryEnter
调用 1 ms (!!!)并且我这样做了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);
}
从日志(以μs为单位),尝试失败〜1ms:
12:55:43:778调试:TryEnter尝试1264 12:55:43:779调试:TryEnter失败2123
从日志(以μs为单位),成功尝试花费~0.01ms:
12:55:49:701调试:尝试尝试889 12:55:49:701调试:尝试输入成功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 ms)Task
每2 ms = 25 000个任务有多好? .NET可以有效地管理这个吗?我也可以使用BlockingCollection
的生产者 - 消费者模式,仅启动50个“工人”,然后每2毫秒向BlockingCollection提交50个项目的新包装?会更好吗?答案 0 :(得分:4)
Parallel.Foreach
,看看它到底有多远。Parallel.ForEach
。我还要确保strategies
的类型为IList
,以便在不等待迭代器的情况下尽可能多地触发项目。您尚未将代码粘贴到OnAllTablesUpdated(),您在该过程的持续时间内保持锁定。这将成为你所有可能性的瓶颈。
有些问题,为什么在表准备好处理时使用锁?