Ситуация:
В сети выделен специальный компьютер, задача которого принимать UDP пакеты с
одного канала и рассылать их многим клиентам.
Число клиентов: 500
Данные приходят со скоростью 500 000 bit/sec
Сеть: 1GB
Машина: P4, 1.8 ГГц, Win2k
Теоретический суммарный исходящий трафик: 500 * 500 000 = 250 000 000 < 1GB
Реальное количество компов клиентов ~10, просто на каждом из них настроено
50 IP-адресов на один сетевой интерфейс.
Реализация:
Сейчас программа состоит из двух потоков и буфера.
Один читает данные (recvfrom) с принимающего сокета в буфер.
Другой берет пакеты из буфера по одному и рассылает (sendto) их всем
клиентам используя один сокет в цикле.
Проблемы:
Исходящий трафик не превышает 180 000 000 bit/sec (Windows Performance
analyzer). Причем сторонних пакетов практически не встречается (Ethereal)
Очевидно, часть отправленных пакетов теряется.
Использование процессора — 100%
Анализ показал, что основную часть времени процессор проводит в системных
библиотеках (ntdll.dll, ws2_32.dll и т.д.)
Возможно, время тратится на переходы в режим ядра и обратно при многократных
вызовах sendto()
Пробовал убрать копирование на отсылающем сокете через
setsockopt(SO_SND_BUF, 0) — не помогло.
Ищутся идеи для более оптимальной реализации.
Спасибо.
Здравствуйте, butcher, Вы писали:
>> Другой берет пакеты из буфера по одному и рассылает (sendto) их всем >> клиентам используя один сокет в цикле.
B>можно вот этот код показать?
Пожалуйста
//где-то в хедерахtypedef list<SOCKADDR_IN> OUTAddressList;
typedef list<SOCKADDR_IN>::iterator OUTAddressIterator;
struct CDataHeader
{
WORD index;
WORD alength;
};
struct CDataPacket
{
CDataHeader header;
BYTE data[4]; //actual size is defined by allocated memory
};
//а вот и реализация
CDataPacket* pDP = NULL;
//здесь получаем пакет с бефера
//пропущено
OUTAddressIterator iter;
//блокируем список клиентов
EnterCriticalSection(&m_csList);
//шлем пакет всем зарегистрированым клиентамint nSent = 0;
OUTAddressIterator end = m_OUTAddresses.end();
for(iter = m_OUTAddresses.begin(); iter != end; ++iter)
{
SOCKADDR *sock_addr = (SOCKADDR *)&(*iter);
nSent = sendto(m_SendingSocket,(char*)pDP->data,pDP->header.alength,0,sock_addr, sizeof(SOCKADDR_IN));
}
LeaveCriticalSection(&m_csList);
//освобождаем пакет
//пропущено
Здравствуйте, yslag, Вы писали:
Y>Ситуация: Y>В сети выделен специальный компьютер, задача которого принимать UDP пакеты с Y>одного канала и рассылать их многим клиентам.
Y>Число клиентов: 500 Y>Данные приходят со скоростью 500 000 bit/sec Y>Сеть: 1GB Y>Машина: P4, 1.8 ГГц, Win2k Y>Теоретический суммарный исходящий трафик: 500 * 500 000 = 250 000 000 < 1GB Y>Реальное количество компов клиентов ~10, просто на каждом из них настроено Y>50 IP-адресов на один сетевой интерфейс.
[...skipped...]
Размеры отправляемых пакетов как варьируются?
... << RSDN@Home 1.1.2 stable >>
С уважением, Николай.
Re[2]: Много клиентов и большой трафик
От:
Аноним
Дата:
12.02.04 09:57
Оценка:
Здравствуйте, Lostar, Вы писали:
L>[...skipped...] L>Размеры отправляемых пакетов как варьируются?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Lostar, Вы писали:
L>>[...skipped...] L>>Размеры отправляемых пакетов как варьируются?
А>~40% — 1312 байт А>~40% — 52 байта А>остальное — разные пакеты (100 — 1200 байт)
А>Почему-то я думал что основная масса пакетов будет близкой к MTU А>Сейчас попробую убрать большую часть 52-байтных пакетов. А>Спасибо за подсказку.
А>Но все-же я думаю это не решит проблемы целиком (уменьшить загрузку CPU и приблизиться к 1GB так как входной поток может быть больше 500 000 bit/sec)
Убрал 52-байтные пакеты полностью.
загрузка CPU упала до 80%
исходящий трафик не увеличился (остался на уровне 180 000 000 bit/sec)
Увеличил входной канал до 1 000 000 bit/sec
загрузка CPU и исходящий трафик не изменились (80 и 180 000 000)
Здравствуйте, yslag, Вы писали:
Y>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Lostar, Вы писали:
L>>>[...skipped...] L>>>Размеры отправляемых пакетов как варьируются?
А>>~40% — 1312 байт А>>~40% — 52 байта А>>остальное — разные пакеты (100 — 1200 байт)
А>>Почему-то я думал что основная масса пакетов будет близкой к MTU А>>Сейчас попробую убрать большую часть 52-байтных пакетов. А>>Спасибо за подсказку.
А>>Но все-же я думаю это не решит проблемы целиком (уменьшить загрузку CPU и приблизиться к 1GB так как входной поток может быть больше 500 000 bit/sec)
Y>Убрал 52-байтные пакеты полностью. Y>загрузка CPU упала до 80% Y>исходящий трафик не увеличился (остался на уровне 180 000 000 bit/sec)
Y>Увеличил входной канал до 1 000 000 bit/sec Y>загрузка CPU и исходящий трафик не изменились (80 и 180 000 000)
Мы как-то проводили эксперименты и выявили следующую зависимость:
Исходная конфигурация Win2k, посылка пакетов разного размера по TCP, сеть 100 Mb.
при небольших размерах пакета (<1Kb) наблюдается явный провал на графике скорости приема\передачи данных.
при средних\больших пакетах данных (>1Kb) кривая стабилизируется и выходит теоретически максимально возможную (иногда даже превышает немного теоретическую)