javapowered javapowered - 4 years ago 137
C# Question

best way to count how many times per second the method is called

I have dll method that should be "QoSed" - this method should be called maximum 100 times per second.:

private static extern int ExecTrans(int connectionId);


This method used only in one place in program so it's ok to qos this place.
I need separate "qos counter" for each
connectionId
. So
ExecTrans(1)
and
ExecTrans(2)
should go to different counters.

At first iteration I would like to count how often method is called (for each
connectionId
). I.e. I want to have "live statistics". There are two approach:

- 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.


For now I don't care which of these methods to use but I would select one creating less "overhead". I want qos to add as less "extra-work" as possible because it's trading software sensitive to every 0.1 ms.

As for first approach I think I can use something like that (pseude-code, probably
stats
and
curStats
should be made thread-safe):

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];
......
}


As for second approach.... is it possible to make a collection where objects life for exactly one second and after a second disappear? Then every time I will add the next object to a collection unless collection contains 100 objects.

What do you think? I'm not familar with C# library files so probably I'm missing some useful classess, probably you can suggest another approach.

Answer Source

A first approach:

  • Use a ConcurrentQueue<DateTime>
  • Before every request, check the size of the queue. If > 100, cancel the request
  • If < 100, enqueue the current DateTime and execute the request
  • In a background thread, every 0.1 second, remove entries older than 1 second

It should be fairly efficient, but:

  • Since there's no locking between the time you check the queue count and the time you enqueue, you may sometimes get slightly over 100 requests per second
  • Since the background thread executes every 0.1 second, if you receive 100 requests at the same time, it may block the queue for up to 1.1 seconds. Adjust the sleep time as needed.

I may be wrong but I don't think there's a perfect solution. Basically, the more precise the system is, the more overhead there is. You have to adjust the parameters depending on your needs.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download