计算每秒调用该方法多少次的最佳方法
本文关键字:方法 多少次 最佳 调用 计算 | 更新日期: 2023-09-27 18:17:26
我有一个应该" qsed "的dll方法-这个方法应该每秒最多被调用100次:
private static extern int ExecTrans(int connectionId);
这个方法只在程序中的一个地方使用,所以可以qos这个地方。我需要为每个connectionId
单独的"qos计数器"。所以ExecTrans(1)
和ExecTrans(2)
应该去不同的计数器
在第一次迭代中,我想计算调用方法的频率(对于每个connectionId
)。也就是说,我想要"实时统计"。有两种方法:
- allow to exceed limitiation for a short period. for example allow "100 transaction from 0 to 1 second, 100 transaction from 1 to 2 seconds and 200 transactions from 0.5 to 1.5 second".
- at any second interval transactions should not exceed 100.
现在我不关心使用这些方法中的哪一个,但我会选择一个创建较少"开销"的方法。我希望qos添加尽可能少的"额外工作",因为它的交易软件对每0.1毫秒都很敏感。
对于第一种方法,我认为我可以使用类似的东西(伪代码,可能stats
和curStats
应该是线程安全的):
private int[] stats // statistic to display to user
private int[] curStats; // statistic currently collection
OnOneSecondElapsed(object source, ElapsedEventArgs args) {
foreach (conId : connIds) {
stats[conId] = curStats[conId];
curStats[conId] = 0;
}
}
myMethod {
......
ExecTrans(conId);
++curStats[conId];
......
}
对于第二种方法....是否有可能使一个集合的对象正好存在一秒钟,一秒钟后消失?然后每次我都将下一个对象添加到集合中,除非集合包含100个对象。
你觉得怎么样?我不熟悉c#库文件,所以可能我错过了一些有用的类,也许你可以建议另一种方法。
第一种方法:
- 使用
ConcurrentQueue<DateTime>
- 在每个请求之前,检查队列的大小。如果> 100,取消请求
- 如果& lt;100、将当前DateTime排队并执行请求
- 在后台线程中,每0.1秒,删除超过1秒的条目
它应该是相当有效的,但是:
- 由于在检查队列计数和进入队列的时间之间没有锁定,因此您有时可能会获得略高于每秒100个请求的请求
- 由于后台线程每0.1秒执行一次,如果同时接收100个请求,它可能会阻塞队列长达1.1秒。根据需要调整睡眠时间
有一种叫做分析器的工具,它可以精确地完成您正在寻找的功能。你用你的代码运行它,它会告诉你它在每个方法上花费了多少时间,每个方法被调用了多少次。这是一个关于c#分析器的老帖子。如果你是一名专业开发者,你可能已经获得了分析器的公司许可。
如果有人需要测量而不是节流…下面是一个简单的方法,它给出了一个粗略的估计:
class A{
private int _calls;
private Stopwatch _sw;
public A(){
_calls = 0;
_sw = new Stopwatch();
_sw.Start();
}
public void MethodToMeasure(){
//Do stuff
_calls++;
if(sw.ElapsedMilliseconds > 1000){
_sw.Stop();
//Save or print _calls here before it's zeroed
_calls = 0;
_sw.Restart();
}
}
}
在某些情况下,您每秒将被调用超过n次,我假设您只是不想在额外的情况下进行任何实际处理。
可以使用一个同步的Q对象来保存每个连接要处理的事务。调用你的方法只会让数据排队,告诉你应该做什么。然后,在一个单独的处理线程中(一个系统或一个连接一个线程),您可以将操作从队列中取出,并以每0.01秒处理1个操作的速度处理它们。只需在为给定连接排队之前将Q大小截断为100(弹出到100),然后就可以丢弃额外的工作项。
注意:您需要一个精确的计时函数来强制每0.01秒执行一个事务。例如:
Stopwatch watch = new Stopwatch();
int nextPause = watch.Elapsed.Milliseconds + 10;
while (true)
{
//do work (dequeue one item and process it)
int now = watch.Elapsed.Milliseconds;
if( now < nextPause ) {
Thread.Sleep( nextPause - now );
}
nextPause = watch.Elapsed.Milliseconds + 10;
}
注意:如果一个事务花费的时间超过10毫秒(1/100秒),您可能会丢掉额外的工作项…
如果你想让工作线程更"突发",你可以在一个循环中处理多个工作项,并使用更长的等待时间,这将需要部分等待和部分"剩余项目"计数。(另外,最好使用Monitor。脉搏和脉搏。)