计算每秒调用该方法多少次的最佳方法

本文关键字:方法 多少次 最佳 调用 计算 | 更新日期: 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毫秒都很敏感。

对于第一种方法,我认为我可以使用类似的东西(伪代码,可能statscurStats应该是线程安全的):

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。脉搏和脉搏。)