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

时间:2011-12-09 17:02:43

标签: c#

我的dll方法应该是“QoS” - 这个方法应该每秒最多调用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毫秒都很敏感。

至于第一种方法,我认为我可以使用类似的东西(pseude-code,可能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#库文件,所以可能我错过了一些有用的classess,可能你可以建议另一种方法。

4 个答案:

答案 0 :(得分:7)

第一种方法:

  • 使用ConcurrentQueue<DateTime>
  • 在每个请求之前,检查队列的大小。如果&gt; 100,取消请求
  • 如果&lt; 100,将当前DateTime排队并执行请求
  • 在后台线程中,每0.1秒删除超过1秒的条目

它应该相当有效,但是:

  • 由于在您检查队列计数和排队时间之间没有锁定,您有时可能会每秒略微超过100个请求
  • 由于后台线程每0.1秒执行一次,如果同时收到100个请求,它可能会阻塞队列最多1.1秒。根据需要调整睡眠时间。

我可能错了,但我认为这不是一个完美的解决方案。基本上,系统越精确,开销越大。您必须根据需要调整参数。

答案 1 :(得分:3)

有一个名为探查器的工具可以完全满足您的需求。你用你的代码运行它,它会告诉你它在每个方法中花费了多少时间以及每个方法被调用了多少次。这是关于C#个人资料的old thread。如果您是专业开发人员,则可能已获得分析器的公司许可。

答案 2 :(得分:2)

如果有人需要衡量而不是限制......这是一种天真的方法,可以给你一个粗略的估计:

cholmod_dense

答案 3 :(得分:1)

在某些情况下,您每秒会被调用超过n次,我假设您只是不想在额外情况下进行任何实际处理。

您可以使用同步的Q对象来保存要为每个连接处理的事务。调用您的方法只会将数据排入队列,说明应该做什么。在一个单独的处理线程中(或者只有一个用于系统或每个连接),然后您可以将操作出列并以1 / 0.01秒的速率处理它们。在将每个工作单元排入给定连接之前,只需将Q大小截断为100(弹出到100),然后丢弃额外的工作项。

注意:您需要一个精确的计时功能,每0.01秒执行一次事务。 e.g:

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.Pulse和Montior.Wait而不是睡觉......)