HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

qos method call using DateTime and Stopwatch

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stopwatchqosmethodcallusinganddatetime

Problem

I need to limit method call to 80 times per second (for each connectionId).

My initial version:

private const int MAX_TRANSACTIONS_PER_PERIOD = 80;
private const int PERIOD_IN_MS = 1000;
private Queue[] times = new Queue[10]
{
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100),
    new Queue(100)
};

private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
    DateTime nowTime = DateTime.Now;
    while (times[connection_id].Count > 0 && (nowTime - times[connection_id].Peek()).TotalMilliseconds >= PERIOD_IN_MS)
    {
        times[connection_id].Dequeue();
    }
    if (times[connection_id].Count >= MAX_TRANSACTIONS_PER_PERIOD)
    {
        Thread.Sleep(PERIOD_IN_MS - (int) (nowTime - times[connection_id].Dequeue()).TotalMilliseconds);
    }
    times[connection_id].Enqueue(DateTime.Now);

    return ExecTrans(connection_id, name, parameters_string, bytes);
}


I've decided to replace DateTime with Stopwatch just because I don't need to store entire Date. I only need to store how many milliseconds elapsed:

```
private const int MAX_TRANSACTIONS_PER_PERIOD = 80;
private const int PERIOD_IN_MS = 1000;
private Queue[] times = new Queue[10]
{
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100),
new Queue(100)
};

private Stopwatch workingTime = Stopwatch.StartNew();

private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
long nowTime = workingTime.ElapsedMilliseconds;
while (times[connection_id].Count > 0 && (nowTime - times[connection_id].Peek()) >= PERIOD_IN_MS)
{
times[connection_id].Dequeue();
}
if (times[connection_id].Count >= MAX_TRANSACTIONS_PER_PERIOD)
{

Solution

StopWatch is definitely better for timing stuff, but the semantics of the two versions are different. With DateTime you have this:

private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
    DateTime nowTime = DateTime.Now;
   ...


and with StopWatch you have that:

private Stopwatch workingTime = Stopwatch.StartNew();
private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
    long nowTime = workingTime.ElapsedMilliseconds;
  ...


Bug?

The stopwatch starts as soon as the instance is created, it looks like you're misusing the stopwatch.

long nowTime = workingTime.ElapsedMilliseconds;


That's not how a stopwatch works. That will give you the number of milliseconds elapsed between the instantiation of your class and the moment ExecTransWithStats gets called. I doubt this is what you are expecting.

Code Snippets

private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
    DateTime nowTime = DateTime.Now;
   ...
private Stopwatch workingTime = Stopwatch.StartNew();
private int ExecTransWithStats(int connection_id, string name, string parameters_string, byte[] bytes)
{
    long nowTime = workingTime.ElapsedMilliseconds;
  ...
long nowTime = workingTime.ElapsedMilliseconds;

Context

StackExchange Code Review Q#6750, answer score: 6

Revisions (0)

No revisions yet.