我需要在2毫秒内执行 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调试:TryEnter尝试889 12:55:49:701调试:尝试输入成功900
所以现在我认为 Monitor.TryEnter
对我来说太昂贵了,不能一个接一个地执行50个策略 . 所以我希望使用_475020这样并行这项工作:
// 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) -
每秒开始50
Task
每秒2 25秒= 25 000个任务有多好? .NET可以有效地管理这个吗?我也可以使用BlockingCollection
的 生产环境 者 - 消费者模式,然后仅启动50 "workers" ONCE,然后每2毫秒向BlockingCollection提交50个项目的新包装?会更好吗? -
你如何执行50个方法,每2毫秒(每秒500次)可以并行,每秒总共25 000次?
1 回答
Monitor.TryEnter(object)只是Monitor.TryEnter(object,0,ref false)(0毫秒超时) . 如果没有获得锁定,那1毫秒只是尝试获取锁定的开销 .
您可以根据需要启动任意数量的任务,它们都使用ThreadPool,但这将限制为最大线程数 . 最大值取决于您的系统,内核数量,内存等...它不会是25,000个线程_475028会遇到麻烦 . 我只是使用
Parallel.Foreach
,看看它到底有多远 .Parallel.ForEach
. 我还要确保strategies
的类型为IList
,以便在不等待迭代器的情况下尽可能多地触发 .您尚未将代码粘贴到OnAllTablesUpdated(),您在该过程的持续时间内保持锁定 . 这将成为你所有可能性的瓶颈 .
有些问题,为什么在表准备好处理时使用锁?
代表不可能吗?
为什么在运行策略时锁定它?您是否在每个策略中修改该表?如果是这样的话你能不复制一份吗?