Пишу сервер, все входящие сообщения храню в контейнере std::queue, т.к. работают с одной очередью много потоков,- реализована внешняя синхронизация. Во время тестирования системы, на DDOS (поводилось под ОС Win 2000 Profesional build 5.00.2195 SP3 RAM 512 MB AMD Athlon 2.5 Barton SL-FRN2). Загрузка процессора 100% при этом время ядра 90-95%, в TaskManager-е, заметил, что происходит 10 — 40 тысяч ошибочных обращений к памяти в секунду. Возможная причина: приняв пакет с данными от клиента сервер запоминает его в пямяти, причем страница памяти перегрузается в файл подкачки и помечается как не доступная, далее при обращении к ней генерируется прерывание и ядро системы загрузает её в ОП из свопа.
Вопрос: есть ли способ запретить сохранение страниц в память. Ну а если мой диагноз неверен, буду рад услышать Вашы рассуждения. Заранее благодарен.
P.S. При отключении сохранения пакетов в очередь, т.е. получаю и игнорирую его. Используя подключение типа LOOP_BACK скорость получения данных была в районе 200 MB в секунду время ядра 5-10%.
Здравствуйте, .erax, Вы писали:
E>P.S. При отключении сохранения пакетов в очередь, т.е. получаю и игнорирую его. Используя подключение типа LOOP_BACK скорость получения данных была в районе 200 MB в секунду время ядра 5-10%.
покажи
1.сохранение пакетов в очереди
2.цикл обработки сообщений из очереди
Здравствуйте, ssm, Вы писали:
ssm>Здравствуйте, .erax, Вы писали:
E>>P.S. При отключении сохранения пакетов в очередь, т.е. получаю и игнорирую его. Используя подключение типа LOOP_BACK скорость получения данных была в районе 200 MB в секунду время ядра 5-10%.
ssm>покажи ssm>1.сохранение пакетов в очереди ssm>2.цикл обработки сообщений из очереди
1. при добавлении пакетов в очередь, надо ее блокировать. у тебя этим и не пахнет
2. std::queue не имеет метода Pop(), у нее есть front() и pop()
3. нафига столько блокировок в основном цикле? вот версия с критической секцией:
Здравствуйте, ssm, Вы писали:
ssm>Здравствуйте, .erax, Вы писали:
ssm>1. при добавлении пакетов в очередь, надо ее блокировать. у тебя этим и не пахнет
Я же сказал что использую внешнюю синхроницацию. ssm>2. std::queue не имеет метода Pop(), у нее есть front() и pop()
ssm>3. нафига столько блокировок в основном цикле? вот версия с критической секцией: ssm>суть в том, чтобы входить в крит. секцию, только когда это действительно необходимо. а у тебя получется все время происходит синхронизация
Да, я извиняюсь, что сразу не написал этого. Вчера тестировал момент
на возможность тормозов изза синхронизации. Вместо мютексов в винде используются крит. секции, ну а в Линуксе,- мютексы.
Дошло до того, что тело функций Lock() и Unlock() оставил пустыми, т.е. никакой синхронизации небыло вообще. Цирк в том, что тест стабильно проработал целую ночь, 5 компов с 300 клиентами на каждом, плюс 200 на локалхосте, итого 1700 клиентов, сам сервак разбился на 27 читающих потоков по 64 клиента на каждый, прлюс один поток-акцептор (в котором происходит вызов accept) и один поток для обработки очереди сообщений. Тест заключался в том, что клиент шлет пакет типа:
сервер отправлает его обратно клиенту, на котором собирается статистика по времени прохождения пакета, модифицируется время и снова отправляется клиенту.
Прикол в том, что без синхронизации все отработало 16 часов без единого гюка. Через сервер прошло ~580 ГБ данных (89% с локалхоста).
Время ядра осталось на том же уровне.
Конечно можно сделать вывод о потокозащищенности std::queue .
Я ж говорю, что ядро грузится изза промахов по памяти. ssm>4. в cMPPacketQueue::Push(SServerPacket *_packet) нужен семафор на m_QueueMaxLimit потоков
???
Здравствуйте, .erax, Вы писали:
E>Здравствуйте, ssm, Вы писали:
ssm>>Здравствуйте, .erax, Вы писали:
ssm>>1. при добавлении пакетов в очередь, надо ее блокировать. у тебя этим и не пахнет E>Я же сказал что использую внешнюю синхроницацию.
в каком смысле?
E>Время ядра осталось на том же уровне.
что и с блокировками? нереально!!!
E>Конечно можно сделать вывод о потокозащищенности std::queue .
E>Я ж говорю, что ядро грузится изза промахов по памяти. ssm>>4. в cMPPacketQueue::Push(SServerPacket *_packet) нужен семафор на m_QueueMaxLimit потоков E>???
смысл твоего m_QueueMaxLimit какой?
эта..., а ну ка убери все
try
{
//...
}
catch(...)
{
//...
}
они все равно нафиг не нужны, std::queue не кидает исключений.
Здравствуйте, ssm, Вы писали:
E>>Я же сказал что использую внешнюю синхроницацию. ssm> в каком смысле?
... внешнюю для класса cMPPacketQueue. Этот клас просто некоторый интекфейс, просто в случае какой либо смены контейнера придется переписань несколько строк в этом классе. Была идея делать синхронизацию внутри класса, но из-за особенностей мютексов (на которых до вчера все работало) возникали взаимоблокировки в рамках одного потока.
E>>Время ядра осталось на том же уровне. ssm>что и с блокировками? нереально!!!
веришь, у самого глаза на лоб полезли вчера вечером когда убрал синхронизацию, т.к. думал что именно в ней и дело, я б с такими вобросами в RSDN не обращался.
E>>Конечно можно сделать вывод о потокозащищенности std::queue . ssm>
E>>Я ж говорю, что ядро грузится изза промахов по памяти. ssm>>>4. в cMPPacketQueue::Push(SServerPacket *_packet) нужен семафор на m_QueueMaxLimit потоков E>>???
ssm>смысл твоего m_QueueMaxLimit какой?
самый простой когда размер очереди сообщений больше m_QueueMaxLimit в нее пакеты не ложим(просто забываем).
тупо,- но действенно.
ssm>они все равно нафиг не нужны, std::queue не кидает исключений.
о еще как выбрасывает особенно когда свободной памяти 0 байт.
обнаружил это случайно,- провтыкал както — пакеты в очередь ложу, но не выгребаю, когда очередь заняла 2 ГБ памяти (больше в 32х разрядных системах нельзя выделять под нужды одного процесса, т.е. можно адресовать 4 но остальные два — резерв системы), — ооо такие исключения посыпались, что мама не горюй. А сейчас когда памяти нет, пакет тоже просто теряется, чем сохраняет работосмособность всей системы, я думаю лучже забыть один пакет чем вырубить весь сервак.
Здравствуйте, .erax, Вы писали:
ssm>>они все равно нафиг не нужны, std::queue не кидает исключений. E>о еще как выбрасывает особенно когда свободной памяти 0 байт. E> обнаружил это случайно,
убери для эксперимента, что бы проверить что действительно так тупит
ты с пустым цыклом проверял?
если без Sleep(1) загрузка ядра порядка ~40-45% с мютексами, ~35-40% c крит секциями, ~1-3% без ничего(с заглушками).
Ну а если со слипом, то ничего не видно, т.к. общая загрузка — 0%.
Проблема в ПРОМАХАХ по ПАМЯТИ!!!!
E>если без Sleep(1) загрузка ядра порядка ~40-45% с мютексами, ~35-40% c крит секциями, ~1-3% без ничего(с заглушками).
E>Ну а если со слипом, то ничего не видно, т.к. общая загрузка — 0%.
блин, ну теперь начинай добавлять по одному методу, пока не увидишь, что РЕАЛЬНО грузит проц.
E>Проблема в ПРОМАХАХ по ПАМЯТИ!!!!
да погоди, не надо тока пока кричать, я думаю, что проблема в каком-то из методов
ssm>да погоди, не надо тока пока кричать, я думаю, что проблема в каком-то из методов ssm>mtserverClass->Send(...);
Проверено когда отключал очередь вообще. Т.е. recv и сразу send. Здесь все нормально.
ssm>mtserverClass->OnReceive(...);
просто заглушка в ней ничего нет, сделана для интерфйса с наследующим классом.
ssm>safe_delete(...);
макрос if(...) {detete ...; ...=NULL}
... эта штука ядро не грузит вообще (по крайней мере в диспетчере задач визуально не заметно, проц в целом — да на все 100%).
Здравствуйте, ssm, Вы писали:
E>>... остались операции по работе с очередью. ssm>оставь только операции с очередью и убери mtserverClass->Send(...), что бы убедится
Здравствуйте, .erax, Вы писали:
E>Здравствуйте, ssm, Вы писали:
E>>>... остались операции по работе с очередью. ssm>>оставь только операции с очередью и убери mtserverClass->Send(...), что бы убедится
E>да, дело в операциях с очередью.
НЕТ, дело НЕ в операциях с очередью. я накалякал ниже простой примерчик, суть которого:
есть сервер, умеющий выполнять асинхронно комманду(Command::execute)
есть 100 клиентов(работают в отдельных потоках), каждый из которых просит сервер асинхронно выполнить 20 комманд. При выполнении примера, загрузка процессора 0-1%, если интерестно поиграй с количеством клиентов и комманд. Все сделано на одной критической секции, для std::queue