Производительность отладки сети по минимальной пропускной способности приложения Winsock2 - PullRequest
2 голосов
/ 23 октября 2009

У меня очень простой TCP-клиент Winsock2 (полный список которого приведен ниже), который просто обрабатывает несколько байтов. Тем не менее, он работает очень медленно по сети; данные просто поступают.

Вот что я попробовал и нашел (оба компьютера с Windows находятся в одной локальной сети):

  • Запуск этого приложения с одного компьютера на другой выполняется медленно - для отправки 8 МБ требуется ~ 50 с.
  • Два разных сервера - netcat и пользовательский (такой же простой, как у приведенного ниже клиента) - дали одинаковые результаты.
  • taskmgr показывает, что процессор и сеть практически не используются.
  • Запуск этого приложения с сервером на той же машине выполняется быстро - для отправки 8 МБ требуется ~ 1-2 с.
  • Другой клиент, netcat, работает просто отлично - для отправки 20 МБ данных требуется ~ 7 с. (Я использовал nc, который поставляется с Cygwin.)
  • Изменение размера буфера (1 * 4096, 16 * 4096 и 128 * 4096) не имеет большого значения.
  • Выполнение почти одинакового кода на компьютерах с Linux в другой локальной сети работало просто отлично.
  • Добавление нескольких операторов печати к вызову send показывает, что мы проводим большую часть нашего времени, блокируя его.
  • На стороне сервера мы видим группу приемов из <= 4K блоков (независимо от того, какой размер буфера отправляет отправитель). Однако это происходит и с другими клиентами, такими как netcat, который работает на полной скорости. </li>

Есть идеи? Заранее спасибо за любые советы.

#include <winsock2.h>
#include <iostream>

using namespace std;

enum { bytecount = 8388608 };
enum { bufsz = 16*4096 };

int main(int argc, TCHAR* argv[])
{
  WSADATA wsaData;
  WSAStartup(MAKEWORD(2,2), &wsaData);

  struct sockaddr_in sa;
  memset(&sa, 0, sizeof sa);
  sa.sin_family = AF_INET;
  sa.sin_port = htons(9898);
  sa.sin_addr.s_addr = inet_addr("157.54.144.70");
  if (sa.sin_addr.s_addr == -1) {
    cerr << "inet_addr: " << WSAGetLastError() << endl;
    return 1;
  }

  char *blob = new char[bufsz];
  for (int i = 0; i < bufsz; ++i) blob[i] = (char) i;

  SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  if (s == INVALID_SOCKET) {
    cerr << "socket: " << WSAGetLastError() << endl;
    return 1;
  }

  int res = connect(s, reinterpret_cast<sockaddr*>(&sa), sizeof sa);
  if (res != 0) {
    cerr << "connect: " << WSAGetLastError() << endl;
    return 1;
  }

  int sent;
  for (int j = 0; j < bytecount; j += sent) {
    sent = send(s, blob, bufsz, 0);
    if (sent < 0) {
      cerr << "send: " << WSAGetLastError() << endl;
      return 1;
    }
  }

  closesocket(s);

  return 0;
}

Ответы [ 3 ]

2 голосов
/ 23 октября 2009

Вот то, что вы можете сделать, чтобы улучшить изображение.

  • Вы можете проверить, сколько времени он проводит внутри «соединяй», «отправляй» вызовы API. Вы можете увидеть, является ли проблема с вызовом подключения. Вы можете сделать это с помощью профилировщика, но если ваше приложение работает очень медленно, вы сможете увидеть его во время отладки.
  • Попробуйте запустить Wireshark (или Ethereal) для выгрузки сетевого трафика, чтобы вы могли видеть, что TCP-пакеты передаются с некоторой широтой. Если ответы приходят быстро, это касается только вашей системы. Если вы обнаружите задержки, то это проблема маршрутизации / сети.
  • Вы можете запустить «печать маршрута», чтобы проверить, как ваш компьютер отправляет трафик на конечный компьютер (157.54.144.70). Вы сможете увидеть, используется ли шлюз, и проверить приоритет маршрутизации для разных маршрутов.
  • Попробуйте отправить более мелкие куски. (Я имею в виду изменение "bufsz" на 1024). Есть ли корреляция между производительностью и размером буфера?
  • Проверьте, установлены ли антивирус, брандмауэр? Обязательно выключите его. Вы можете попробовать запустить это же приложение в безопасном режиме с поддержкой сети.
1 голос
/ 23 октября 2009

Приложение выглядит нормально, и вы сказали, что оно отлично работает с Linux. Не знаю, поможет ли это вам, но я бы сравнил - 1) Значения mtu окон с системой linux. 2) проверил размер получаемой памяти в Windows и Linux. 3) проверил, одинаковы ли скорости сетевой карты обеих систем.

0 голосов
/ 27 октября 2009

Я наблюдал за пакетами, используя Microsoft Network Monitor (netmon) с красивым TCP Analyzer визуализатором, и оказалось, что тонны пакетов теряются и нуждаются в повторной передаче - следовательно, медленные скорости из-за таймаутов повторной передачи (RTO).

Коллега помог мне отладить это:

Ну, из этой трассировки на стороне получателя определенно похоже, что некоторые пакеты не попадают в получатель. Я также вижу, что эти следы выглядят как искаженные пакеты (например, частичные заголовки TCP и т. Д.).

Даже в «хорошем» следе (взгляд получателя на клиент netcat) я вижу некоторые искаженные пакеты (неправильная длина данных TCP и т. Д.). Однако ошибки встречаются не так часто, как на других трассах.

Учитывая, что эти машины находятся в одной подсети, нет маршрутизатора, который мог бы отбрасывать пакеты. Это оставляет две сетевые карты, кабели Ethernet и коммутаторы Ethernet. Вы можете попытаться изолировать неисправную машину, добавив в микшер третью машину, и попробовать тот же тест, когда новая машина заменит сначала отправителя, а затем получателя. Используйте другой физический порт для третьей машины. Если какая-либо из оригинальных машин имеет переключатель между ней и полом, попробуйте удалить этот переключатель из уравнения. Вы также можете попробовать реверсивный кабель Ethernet между двумя исходными компьютерами (или другой Ethernet-коммутатор, к которому вы подключаете две машины напрямую) и посмотреть, сохраняется ли проблема.

Поскольку проблема, похоже, зависит от содержимого пакета, я сомневаюсь, что проблема в кабельной системе. Учитывая, что у отправителя есть Ethernet-чипсет NVidia nForce, а у получателя - Broadcom Ethernet, мои деньги лежат на плате NIC отправителя. Если кажется, что это ошибка определенного сетевого адаптера, попробуйте отключить специальные функции сетевого адаптера, такие как разгрузка контрольной суммы или разгрузка при большой отправке.

Я попытался использовать третий ящик в качестве отправителя (идентичный исходному отправителю, Shuttle XPC с набором микросхем nForce), и это работало гладко - TCP Analyzer показал очень слаженные сеансы TCP. Это наводит меня на мысль, что проблема была в действительности из-за неисправного сетевого адаптера / драйвера на исходной коробке отправителя или из-за плохого кабеля Ethernet.

...