QoS на вызов метода, используя DateTime и секундомер


Мне нужно ограничить вызов метода до 80 раз в секунду (для каждого connectionid содержит).

Мой первоначальный вариант:

private const int MAX_TRANSACTIONS_PER_PERIOD = 80;
private const int PERIOD_IN_MS = 1000;
private Queue<DateTime>[] times = new Queue<DateTime>[10]
{
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(100),
    new Queue<DateTime>(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);
}

Я решил заменить Датавремя с секундомером, просто потому что мне не нужно хранить всю дату. Мне нужно только хранить сколько миллисекунд:

private const int MAX_TRANSACTIONS_PER_PERIOD = 80;
private const int PERIOD_IN_MS = 1000;
private Queue<long>[] times = new Queue<long>[10]
{
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(100),
    new Queue<long>(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)
    {
        Thread.Sleep(PERIOD_IN_MS - (int) (nowTime - times[connection_id].Dequeue()));
    }
    times[connection_id].Enqueue(workingTime.ElapsedMilliseconds);

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

Я правильно понял, что версия с секундомером лучше? Он имеет гораздо более высокую точность, но я нормально с точностью Датавремя (10-15 МС). Должен ли я платить за дополнительную точность (которой я на самом деле не нужны)?



285
5
задан 12 декабря 2011 в 09:12 Источник Поделиться
Комментарии
1 ответ

Секундомер - это однозначно лучше для времени, но и семантику двух вариантах разные. С Датавремя у вас есть это:

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;

Это не так, как секундомер работает. Это даст вам количество миллисекунд, прошедшее между созданием экземпляра класса и на момент ExecTransWithStats вызывается. Я сомневаюсь, что это то, что вы ожидаете.

6
ответ дан 13 февраля 2014 в 05:02 Источник Поделиться