Я уже вся заждалась, измаялась и даже немного всплакнула

Не так давно попалась в руки одна ошибка. Проявлялась она в том, что некое приложение, общающееся с коллегой через TCP/IP соединение, жаловалось на то, что пересылка пакетов по сети занимает около получаса, и что, вообще, заставлять девушку ждать более 300 миллисекунд – неприлично. Впрочем, судя по тому, что приложение работало как ни в чем не бывало, - замечание про полчаса ожидания было легким преувеличением. Для полноты картины добавлю, что то приложение было в процессе переноса на другую платформу с целью «чиста позапускать» (и посмотреть, как оно там работает).

Кусок кода, выводящий сообщение нашелся быстро. Однако на код, вычисляющий задержку, пришлось немного помедитировать. Как следует помедитировав отладчиком, удалось выделить алгоритм вычисления задержки, который выглядел примерно вот так:

  1. Клиент посылает текущее время вместе с пакетом:

    message->timestamp = (DWORD)QueryPerformanceCounter();
    send(message);
    
  2. Сервер прибавляет свое время при приеме пакета и отнимает - при посылке:

    message->timestamp += (DWORD)QueryPerformanceCounter();
    ...
    message->timestamp -= (DWORD)QueryPerformanceCounter();
    send(message);
    
  3. Клиент сравнивает текущее время с полученным в пакете:

    DWORD delta = (DWORD)QueryPerformanceCounter() - message->timestamp;
    double latency = (double)delta / QueryPerformanceFrequency();
    

Фактически клиент меряет время, прошедшее между отправкой и приемом пакета, за вычетом времени на обработку пакета сервером. Трюк с использованием младших 4-х байт счетчика хотя и не очень красив, но работает при условии что, один DWORD покрывает интервал заведомо больший, чем максимальная задержка пакета.

Причина ошибки оказалась в том, что частота таймера высокого разрешения оказалась различной на порядки на клиенте и сервере. Допущение, что все машины используют одинаковую частоту таймера высокого разрешения было верным до тех пор, пока приложение не попало в сильно отличное от стандартного окружение.

comments powered by Disqus