-
> Eraser © (06.02.16 16:17) [14] Отправил на мыло эхо-демо.
-
> Nouser © (07.02.16 03:02) [20]
получил, спасибо!
-
> чем меньше задержки, тем лучше.Открыл Рихтера - увидел SetFileCompletionNotificationModes , прикрутил - таки да, можно несколько сэкономить на переключениях потоков. Еще есть SetFileIoOverlappedRange , видимо для того чтобы дать возможность драйверу работать напрямую (без лишнего копирования) с пользовательским буфером. Пока не крутил, но заманчиво.
-
> Nouser © (07.02.16 03:02) [20] > > Eraser © (06.02.16 16:17) [14] > Отправил на мыло эхо-демо.
видимо вещь очень узко заточенная под конкретную задачу, в целом, много полезного, думаю применение найдется. > DVM © (06.02.16 16:42) [15]
> Наверное ты вот это видел, но приведу ссылку на всяк случай > https://github.com/bamlan/delphi-iocp-framework > > я его проверял, оно быстро работает.
по началу обрадовался, прикрутить удалось на место ICS буквально за час. Работает быстро, все то что надо. НО всплыла проблема, с которой я сталкивался и раньше. Здесь она не решена вообще никак. На хорошо загруженном сервер (около 500 нагруженных соединений, причем они коннектятся и отваливаются десятками в секунду, так надо) начинает происходить простая и очень удручающая вещь. А именно - не на каждый WSASend приходит соответствующее событие завершения в порт. В итоге получаем серьезную утечку ресурсов. Буквально за 5-10 минут работы легко может съесть 1 Гб памяти. Причем сам фреймворк отображает где именно. Да и провел простой эксперимент, посчитав количество WSASend и его завершений - все именно так. Еще больше удручает то, что в сети нет упоминаний о данной проблеме. Код вызова WSASend и обработка завершения в компоненте выглядят корректно, да и видно, что фреймоворк не школьник писал и для работы. Вот и думаю, то ли лыжи не едут, то ли я..
-
> А именно - не на каждый WSASend приходит соответствующее > событие завершения в порт.
дело, конечно же, оказалось не в IOCP, а во фреймворке, автор не до конца освобождал блоки память.
-
> Eraser © (10.02.16 23:08) [24]
> автор не до конца освобождал блоки память.
так может ты напишешь где он не освобождал? или еще лучше автору написать.
-
> DVM © (12.02.16 21:34) [25]
в procedure TIocpIoThread.Execute; модуля Iocp.TcpSocket есть такой участок: if not IocpStatusOk then begin if (PerIoData = nil) and (Connection = nil) then begin LastErr := GetLastError; //if (LastErr <> ERROR_ABANDONED_WAIT_0) then AppendLog('%s IoThread %d ERROR %d=%s', [FOwner.ClassName, ThreadID, LastErr, SysErrorMessage(LastErr)], ltError); Break; end;
if (PerIoData <> nil) then begin if PerIoData.Operation = iotWrite then begin FOwner.IoCachePool.FreeMemory(PerIoData.Buffer.DataBuf.Buf); end;
FOwner.FreeIoData(PerIoData); end;
if (Connection <> nil) then begin Connection.Release; // 对应PostRead/PostWrite中的AddRef Connection.Disconnect; // 对应连接创建时的FRefCount := 1 end;
Continue; end; собственно, вот этой строки не хватало if PerIoData.Operation = iotWrite then begin FOwner.IoCachePool.FreeMemory(PerIoData.Buffer.DataBuf.Buf); end;
т.к. в MSDN есть такой текст If *lpOverlapped is not NULL and the function dequeues a completion packet for a failed I/O operation from the completion port, the function stores information about the failed operation in the variables pointed to by lpNumberOfBytes, lpCompletionKey, and lpOverlapped. To get extended error information, call GetLastError.https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa364986(v=vs.85).aspx Собственно, дальше PerIoData освобождалась, а вот PerIoData.Buffer.DataBuf.Buf - нет, данные повисали в воздухе, точнее в пулле, помеченные как занятые. В целом, вот уже неделю занят отладкой и ковырянием данного фреймворка и кода, связанного с ним, но там проблемы скорее из-за специфики моего функционала. Если правильно настроить кэши, то производительности для моих нужд хватает. вообще удивительно, почему нет ни одного приличного и полностью отлаженного инструмента. во всех таких проектах главная проблема - переоптимизация, авторы боятся потратить лишний мегабайт памяти или лишний такт процессора, в итоге, страдает архитектура, причем сильно. а что памяти пустой полно, что процессор не загружен, только AV сыпаться, а так ничего )
-
кстати, пришлось еще добавить в пулл объектов еще одну очередь удаленных объектов, из которой они уже окончательно освобождаются строго, после указанного интервала. Некий примитивный GC. Того подхода, который был изначально не хватало, приводило к AV.
Вообще беда таких проектов - отсутствие инфраструктуры для отладки. Естественно на 10 или 100 соединениях все будет работать нормально, а вот под нагрузкой мельчайшие недоработки рано или поздно вылезают, классика. Приходится заниматься отладкой на боевом сервере, к сожалению.
|