All streams
Search
Write a publication
Pull to refresh
482
0
Send message
Спасибо за ответ.
Небольшая поправка (думаю, Вы это и так знаете, но просто уточню для тех, кто будет читать). «Чистый» без примесей асинхронный ввод/вывод в Win32 имеет название overlapped (и использует структуру OVERLAPPED). IOCP — это не совсем асинхронный ввод/вывод. Строго говоря — они вообще «ортогональны» асинхронности ввода/вывода и занимаются в точности описанной в данном посте проблемой. Просто использование IOCP в паре с асинхронным вводом/выводом является наиболее эффективным и в то же время уступающим по удобству только полностью синхронному вводу/выводу без всяких изысков.
выбираются по принципу FIFO

LIFO, идиот!!!1111
Боюсь что в контексте сетевого приложения говорить про latency и иметь в виду затраты на дополнительный сискол, а не увеличение задержки, которое увидит реальный сетевой клиент — это достаточно сомнительная затея.

Боюсь, что класс «сетевых приложений» не ограничивается «хомяками на похапэ». Более того, я за Вас посчитал количество тактов на байт даже на middle-end-овых 1GbE NIC и high-end-овом процессоре (идеальный для Вас случай). Разделить на 10 (40? 100?), надеюсь, сможете сами (да, кстати, оказывается уже несколько лет внедряют 10GbE инфраструктуру на витой паре — каюсь, некоторое время не интересовался конкретно этим вопросом).

Причем речь идет не о задержке между запросом удаленной стороны и ответом на нее сервера, речь идет о задержках между приемом пакета сетевой картой и возможностью приложения увидеть данные из этого пакета, а сетевому стеку — продвинуть окно. То есть о задержках ВНУТРИ ПОТОКА. Как Вам понравится если Ваш 1 гигабит ВНЕЗАПНО превратится в 500 (среднепотолочное значение — можете не придириаться) мегабит? А если в те же 500 мегабит превратится 10 гигабит (процессор то не ускоряется с «ускорением» сетевой карты)?

А в случае с виндой получается что то что пишут на msdn/stackoverflow сотрудники microsoft оказывается неверным, а то что знает он — так работает всё на самом деле

Интересно, где Вы увидели, что написанное «сотрудником Майкрософта оказывается неверным»? Я же вполне ясно сказал, что оно просто не имеет отношения к предмету обсуждения. Точно так же как и Ваши ссылки на «zero-copy» оптимизации в Линуксе. Вообще, подобное разбрасывание ссылками на не относящиеся к обсуждаемому вопросу статьи (авось что-то да «прилипнет») — это довольно явный маркер недостаточной уверенности в этом самом «обсуждаемом вопросе». Хотя чего уж там, Вы же и сами признаете, что знаний в винде у Вас нет, а по Вашему категорическому неприятию концепции асинхронного ввода/вывода (даже prefork/select/poll лучше), смею предположить, что конкретно с ним у Вас тоже опыта нет (хотя опыт сетевого программирования у Вас со всей очевидностью есть).

если вы обратите внимание на начало дискуссии, то увидите что этот человек забежал и начал утверждать то в чём вообще не разбирается, рассказывая про линуксовое aio.

Если Вы обратите внимания, я говорил об асинхронном вводе/выводе, который (НАКОНЕЦ-ТО) появился даже в линуксе (и позиксе). Более того, несколько раз по ходу дискуссии говорил о том, что даже если реализация асинхронного ввода/вывода в линуксе «сосет» (там много чего «сосет» — чего ж теперь от этого всего отказываться?) — это не значит, что асинхронный ввод/вывод «сосет».

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

Э-э-э-э, уважаемый, Вы бы лучше хоть раз на пальцах объяснили, как Вам splice/vmsplice поможет избавиться от двух (Вы же сами утверждали что будет «zero-copy») копирований при «неблокирующем» вводе/выводе. Что же до переключения контекстов и «феерическом бреде», во-первых, Вы очень удачно «не заметили», что я говорил о двух буферах размером с MTU, то есть пока заполняется второй — у нас есть время запостить следующий еще ДО НАЧАЛА обработки данных — просто по факту того, что один буфер уже использован. В нашем случае с 1GbE NIC + 3.6GHz Xeon, имеем почти 50к тактов на все про все. Вполне достаточно чтоб запостить DPC, найти по заголовку пакета нужный сокет нужный сокет, перевести его в сигнализированное (signalled) состояние, запостить в KQUEUE, ассоциированную с этим сокетом (и принадлежащую объекту-IOCP) «событие» о переходе в сигнализированное состояние с переводом в сигнализированное состояние самого объекта IOCP, найти в очереди IOCP WAIT_BLOCK одного из рабочих потоков, ожидающих на этом IOCP и переключить процессор на KTHREAD этого потока. Все операции, кроме поиска нужного сокета (ассоциативный массив из 10k объектов) и, собственно переключения, — тривиальны и примитивны. И, заметьте, нужны В ЛЮБОМ СЛУЧАЕ — хоть в неблокирующем, хоть в асинхронном режиме. Просто в асинхронном режиме операций нужно гораздо меньше. Поиск в ассоциативном массиве — либо константная амортизированная сложность, либо логарифмическая для худшего случая — зависит от используемой структуры данных. Переключение конктекстов — действительно самая дорогостоящая операция (опять таки гарантированно необходимая только раз в отличие от). Сброс TLB кешей заставляет несколько раз сходить в память (повторюсь, это в любом случае, в отличие от совершенно ненужных «походов в память» для перекладывания байтиков из одного буфера в другой), но ситуацию спасает тот факт, что рабочие потоки IOCP выбираются по принципу FIFO — то есть поток, который последним заблокировался на IOCP (скорее всего сразу после обработки предыдущего запроса) будет «разбужен» первым и есть немалая вероятность, что все необходимые ему данные будут в кешах разных уровней (опять таки, сравните, с неблокирующим доступом — где планировщику приходится действовать «наугад» и кучу памяти придется доставать прямиком из RAM — и у меня есть какие то смутные подозрения, что все может накрыться еще серьезнее на NUMA серверах)

Да, странным образом, я в Вас вижу грамотного (хотя и не совсем сдержанного) собеседника, Вы же все норовите перейти на личности (лично я себе такое, к моему сожалению, все еще позволяю, но только если вижу, что технического разговора все равно не получится). А вообще, у меня к Вам вопрос: у Вас такой пиетет перед всеми «молодыми специалистами» из Microsoft или только перед теми, кто пишет на stackoverflow
Зашел плюсануть этот комментарий
Телепатия имеет к этому такое же отношение, как и MAC. Мой хрустальный шар говорит мне, что Вы все-таки получили какое-никакое образование (как минимум среднее). Скажите, имеет ли телепатия отношение к тому, что происходит на экзамене? Если студент начинает пороть откровенную ЧУШЬ, знающему человеку это сразу видно, хотя студент и может считать себя чрезвычайно хитрым и способным «запудрить мозги» любому. Мне очень неприятно Вас огорчать, но «пудрить мозги» — это Вам в МГИМО на теософию. В IT — довольно легко оценить квалификацию и кругозор человека просто побеседовав с ним немного.

ОК, я исправлюсь, MAC спасает в 100% случаев если вы запускаете программу, которая работает заведомо известным способом, запрашивает и заведомо известные ресурсы, в этом случае MAC поможет

Ну блин, ЗАЧЕМ!!! Вы же не можете не осознавать, что не имеете ни малейшего понятия о том, что такое MAC? Зачем Вы продолжаете публично позориться, демонстрируя не просто свою безграмотность, а именно самоуверенную безграмотность?

Хотя ОК, давайте на секунду предположим, что мы с bondbig просто не доросли до Вашего уровня. Расскажите, пожалуйста, каким образом MAC поможет в описанном Вами случае. Ну вот смоделируйте угрозу и покажите, каким образом MAC решает проблему. Да еще и на 100% (100% безопасный линукс это «гы, сына, лол»).
А вообще прежде, чем меня исправят другие, признаю, что MIC не совсем полно реализует модель Биба, что не отменяет абсолютную нерелевантность MAC в данном контексте.
Вот что меня всегда поражало в людях вроде Вас, так это упертость с которой Вы верите, что все остальные ТОЖЕ идиоты и ничего не знают. Нет, ну в самом деле, не можете же Вы не осознавать, что НИЧЕГО не знаете о безопасности. Ну блин почему же Вы пишете так, как будто все Ваши предыдущие комментарии ВНЕЗАПНО стали невидимыми. Напомню:

Старый добрый MAC спасает в 100% случаев. Нет MAC'а — вот и получают и «неуловимые» вирусы/трояны или «ой я случайно удалил эту папочку что мне делать?». Нет MAC'а — приходится ждать обновления антивируса и надеяться что вирусописатели не успеют быстрее антивирусников обновить своё детище, вместо того чтобы просто добавить еще одно правило запрещающее подозрительное действие.


MAC — панацея. MAC — излечит СПИД с малярией в Африке и геморрой у офисных работников. MAC, только MAC.

Если же исключить MAC (который вообще не к месту, а к месту модель целостности Биба, опять-таки ВНЕЗАПНО, реализованная в винде), то SELinux — довольно кривая реализация самого обычного DAC. Да-да, того самого, который в винде уже 20 лет (и пришел туда из VMS, где был еще 30 лет назад — как раз во время, когда поделка, созданная для игры в Space War, изобретала свои триплеты).
Спасибо за откровенное и не оставляющее никаких сомнений признание в том, что Вы действительно не представляете что такое MAC и зачем он нужен. А ведь bondbig ответил раньше Вас — могли бы хотя бы ключевые слова погуглить.
Вы точно уверены, что хотя бы приблизительно понимаете, что такое MAC?
1. Я не совсем про это. All WDM drivers must:
• Include Wdm.h, not Ntddk.h. (Note that Wdm.h is a subset of Ntddk.h.)
• Be designed as a bus driver, a function driver, or a filter driver, as described in Types of WDM Drivers.
• Create device objects as described in WDM Device Objects and Device Stacks.
• Support Plug and Play (PnP).
• Support power management.
• Support Windows Management Instrumentation (WMI).

Ну ладно, IRP_MJ_PNP, IRP_MJ_POWER и IRP_MJ_SYSTEM_CONTROL проходят вниз по стеку и фильтру их обрабатывать не нужно, но создание девайсов в DriverEntry, а не в AddDevice (и включение ntddk.h вместо wdm.h) — это явные признаки legacy драйвера. А фильтры и девайс стеки были всегда — так что это не показатель.

По остальным пунктам — не принимайте близко к сердцу, это так критиканство для галочки (хотя может кому и полезно будет). Статья, повторюсь, мне в целом понравилась.

Сейчас занимаюсь делами далекими от ядра, а опубликовал, потому что пообещал в топике о драйвере на PureBasic.

Это да, сам офигел когда увидел.

Но вообще, если Вы в принципе все еще занимаетесь драйверами (несмотря на то что СЕЙЧАС не занимаетесь), то лучше посмотрите в сторону WDF: фрейворк реализует «канонический» драйвер и стороннему девелоперу нужно только переопределять уникальное для его драйвера поведение (при этом, например в WDM/legacy, логику отмены запроса практически невозможно реализовать правильно, не прочитав специальный документ, а WDF берет всю заботу о подобных вещах на себя). Есть объект «буфер» который хранит указатель, размер и «вместимость» и может быть расширен вызываемой функцией (таким образом не нужно делать два вызова с проверкой на то, хватает ли места) и кучу прочих плюшек.

И да, не стоит использовать DbgPrint — он медленный (весь вывод синхронизируется в отладчик) и поэтому всегда выключен в релизном коде (а WPP/ETW можно включать/выключать в рантайме), он практически не подлежит автоматической обработке, с ним тяжело работать постмортем — при наличии одного только дампа (DebugView имеет какие то эвристики для вытаскивания DbgPrint сообщений из дампа, но это неподдерживаемая фича и никаких гарантий вообще говоря нет) и так далее.
ontl.googlecode.com

А вообще я тоже делал самописную библиотеку оберток над WDM. В конце концов затащил туда исключения и даже вытащил часть KSTL из DriverWorkbench (интересно, их еще кто-то помнит?). Исключения — очень приятная штука, если пользоваться осторожно (хотя в ядре нужно и без исключений быть всегда бдительным)
Э-э-э. Для того, чтобы отказываться от стандартных примитивов (это intrinsic функции и они скомпилируются в код, близкий тому, что у Вас но при этом ВАЛИДНЫЙ для любых платформ и в любых обстоятельствах) нужно иметь причины более веские, чем «не хочется».

Если Вы «без помощи зала» и «звонка гуглу» не сможете ответить на вопрос в чем отличия между InterlockedIncrement, InterlockedIncrementAqcuire, InterlockedIncrementRelease и InterlockedIncrementNoFence, то с вероятностью, близкой к единице, при попытке реализации собственного примитива синхронизации Вы напишете невалидный код. Более того, это будет самая мерзкая разновидность невалидности: race condition на НЕКОТОРЫХ платформах (включая, возможно, будущие IA), к тому же принципиально не трассируемый в отладчике.

Ну и пара «придирок» по мелочам (хотя статья сама по себе неплохая):
1. Ваш драйвер не имеет ничего общего с WDM. Ну то есть вообще. Вижу стандартный legacy драйвер, а вот ни одного признака WDM не вижу. Это не хорошо и не плохо — просто название статьи вводит в заблуждение. А вообще, ознакомьтесь с WDF — он предоставляет немало плюшек по сравнению даже с WDM, не говоря уже о legacy.
2. VS2012 не только имеет темплейты для драйверов (после установки WDK), но умеет сама собирать, умеет сама готовить удаленную машину (включая настройку KD), деплоить туда драйвер, отлаживать, стирать, убирать, готовить есть.
3. DbgPrint/KdPrint — прошлый век же. WPP (или полноценный ETW) — наш метод.
4. Хардкод KeyboardClass0 — нехорошо, лучше IoGetDeviceInterfaces. Это не только поможет прицепиться ко всем клавиатурам, но еще и позволит цепляться ко всем новым через IoRegisterPlugPlayNotification. Ну или использовать WDM и регистрироваться фильтром класса (как делает сам kbdclass)
5. Блокирование Unload до завершения последнего Irp — УЖАСНО. Хотя бы попробовали отменить (IoCancelIrp) их сначала.
Здесь не нужны спинлоки — нужны именно InterlockedXxx функции для рефкаунта
Видел ли кто нибудь массовое падение линукс серверов из-за «високосной секунды»?
вы говорите о теоретическом увеличении задержки в почти два раза

Нет, я говорю о совершенно реальной разнице между одним копированием (если принимать в рассчет общий случай — без TOE) и одним раундтрипом в ядро на критическом пути вместо двух копирований и двух райндтрипов.
На моем ноутбуке двухлетней давности стоит сетевая карта с поддержкой 1 Gig/sec (к слову, стандарта почти пятнадцатилетней давности). Практически все серверные сетевые карты последнего десятилетия поддерживают такую скорость. Внедрение 10 гбит (не говоря уж о 40 или 100) несколько осложняется тем, что медь такие скорости уже не выдерживает и нужна совершенно другая инфраструктура (начиная от сетевых карт и свитчей и заканчивая сетевыми кабелями и «обжимным» инструментом). Так вот, 1 гигабит в секунду — это 125 мегабайт в секунду (Ваш К.О.). У какого нибудь Xeon-а на 3.6 гигагерцах есть всего 29 тактов на байт, чтобы все обработать (параллелится все только на уровне клиентов — критический путь строго последовательный). Пусть даже все контрольные суммы были посчитаны самой картой (TCP Checksum Offload поддерживается даже low-end картами), нам необходимо как минимум одно копирование из буфера сетевой карты в собранный TCP поток. Задержка обращения к памяти может достигать 60 наносекунд (или 200+ тактов нашего 3.6 ГГц процессора). Один раундтрип в ядро — около 1000 тактов. Я не совсем понимаю почему Вам все еще кажется, что лишнее копирование на таких скоростях обмена это так — ничего особенного. Естественно, если на самом верху стека ожидает какой нибудь питон или пэхапэ, то эти микросекунды в общем то и не важны, но даже если не говорить о хайлоаде — зачем делать лишнюю работу, если ее можно не делать?

согласен, но zero-copy можно и без aio, см splice/vmsplice :)

Хм, я уже устал повторять. Одно копирование будет при пересборке пакетов в TCP поток (кроме случаев, когда пересборка происходит аппаратно и в память пишется готовый TCP поток): оно может происходить либо в буфер транспорта либо наприямую в пользовательский буфер ЕСЛИ ОН ЕСТЬ. Второе копирование будет необходимо если этого буфера нет (или Вы предлагаете держать буферы драйвера сетевой карты с пакетами до тех пор, пока не появится запрос на чтение?).
splice/vmsplice поможет только в случае если есть этот самый пользовательский буфер, ожидающий данных. Он может быть либо при синхронном блокирующем чтении либо при асинхронном. При неблокирующем чтении это второе копирование всегда необходимо. Я объяснил это уже три или четыре раза — лень пересчитывать. Если Вы видите, где я неправ — прошу показать каким образом Вы сможете избежать двух копирований при помощи splice/vmsplice и в условиях неблокирующего чтения.

1. не согласен
2. mtu тут вообще не в тему
3. два буфера по 9000байт не сможем, тк нужно выравнивать по размерам страниц :)

MTU при том, что для того, чтобы избежать лишнего копирования, нам достаточно доставки данных из одного пакета — а дальше можно и принять решение о том, как продолжать. Кроме того, зачем нам здесь выравнивание (в не-TOE случае, нас даже DMA не касается, и даже если бы касалось, DMA alignment у большинства устройств значительно меньше страницы)?
Я еще раз посмотрел интерфейс WSK и должен признать, что речь действительно идет о физической памяти (WSK_BUF работает с MDL-ами).

В лучшем случае вспомним времена как было хорошо на модемах :)

Э-э-э-э. Это Вы ушли от ответа или действительно хотите что то сказать?

5. Считаете ли Вы что select, prefork и poll более достойны обсуждения, чем async I/O?

да, считаю

Почему?

Читаем что пишут разработчики Microsoft

Разработчик из Бинга, возраст — 26 лет. То есть стаж — не более 4 лет и при этом не связанный ни с ядром винды вообще, ни с сетевым стеком в частности. Но даже не принимая это во внимание — совершенно неважно, что делает AFD когда нет ожидающего запроса на чтение. Когда такой запрос есть — он уходит напрямую в транспорт.

когда хотим zero-copy(из кернелспэйса в юзерспэйс), то виндовое апи требует выделять физ. память

В общем случае это неверно. Есть три типа обмена: Buffered IO, Direct IO и Neither (type 3) IO. Только один из них (Direct IO) требует физической памяти — собственно для того и создавался (отсюда и название). Это самый эффективный по скорости, но самый «расточительный» способ и именно он используется как TDI так и WSK.

, которая будет использоваться в afd.sys, а не ndis драйвере.

Во первых, afd.sys не нужно выделять никаких дополнительных буферов, если пользователь запостил собственный буфер, но таки да tcpip.sys тоже лочит страницы (для избежания копирования). Собственно наша дискуссия свелась к вопросу о том, что лучше: В ХУДШЕМ СЛУЧАЕ потратить сотню мегабайт физической памяти (в случае с префорками Апача и то зачастую тратится больше) или В ЛЮБОМ СЛУЧАЕ потратить впустую несколько микросекунд на обработку каждого пакета (причем пакеты все равно будут в физической памяти иначе речь пойдет о задержках в десятки-сотни миллисекунд).
Чего то я напортачил с цитированием — ну да ладно, главное что осталось относительно понятно, что к чему
И вообще не пойму о чём речь, открыл я документацию по винде, и что я вижу
Я вот не понимаю, зачем Вы обсуждаете, то в чем, скажем там, не совсем хорошо разбираетесь?

1. Сюрприз!!!111 Все сетевые карты уже минимум лет 10 (может и раньше — не знаю) используют DMA для получения и отсылки пакетов. Так что физическая память ВСЕГДА лочится (DMA, как ни странно, умеет работать только с физической памятью). Другое дело, что для того, чтобы пересобрать пакеты в, собственно, TCP поток по-любому нужно одно копирование. Оно может происходить или прямиком в пользовательский буфер или в буфер драйвера транспортного протокола.
2. Afd.sys не держит буферов. Буферы держит tcpip.sys, а afd.sys — это адаптер инерфейса WinSock2 к TDI/WSK. В любом случае, эти буферы не обязаны быть физическими. Как я уже сказал, физические буферы нужны только NDIS драйверу для получения/отправки данных из/в физической среды. И вот здесь да, при наличии TOE мы можем получать (или отсылать) уже готовый TCP поток прямиком в пользовательский буфер и ВОТ ЭТОТ буфер — должен быть заблокирован в физической памяти, потому что работа с ним идет напрямую через DMA. Да, здесь видим обычный space/time tradeoff, но это, повторюсь, относится к async vs non-blocking I/O только в том плане, что из-за того, что асинхронный ввод/вывод позволяет избавиться от копирования из буфера транспортного протокола в пользовательский буфер, а TOE — от копирования из буферов драйвера сетевой карты в буфер драйвера транспортного протокола, то мы выходим на zero-copy, а в случае неблокирующего ввода/вывода zero-copy невозможен даже если бы Линукс поддерживал TOE.
3. MmProbeAndLockPages не говорит ничего о лимитах. Но это не важно в контексте zero-copy, потому что максимальное количество TOE состояний, которые можно офлоадить из виденных лично мной — 1024. Транспортный протокол использует хитрую эвристику, чтоб аплоадить только длительные соединения, по которым передается много данных (скачивание/закачивание файлов, стриминг медиа и пр.)

В случае без zero-copy, получаем просто громадный оверхед на виртуальную память и значительную потерю производительности из-за этого(цпу кэши, все дела).

Нет, не получаем. Буферы транспортных протоколов (и буферы, которые препостятся приложением при асинхронных операциях) используют demand paging и фактически «не существуют» до момента первого обращения к ним. Место в пейджфайле резервируется, но единственные дисковые операции, которые 100% происходят — это увеличение пейджфайла, если в нем не хватает места.

Или если речь не про винду, то хотелось бы посмотреть у кого это AIO сделано так как надо, на кого стоит равняться.

Да используйте хоть POSIX-овый AIO — все лучше чем «неблокирующие» операции (концептуально — я действительно не знаю, насколько хорошо они РЕАЛИЗОВАНЫ). Кроме того, вот Солярис внедрил IOCP, которые очень близки к виндовым
Ну и дополнительный вопрос (с которого все началось):
5. Считаете ли Вы что select, prefork и poll более достойны обсуждения, чем async I/O?
Это уже несерьезно. Вот статья того же автора, в которой он рассказывает как синхронизировать несколько асинхронных операций, которые могут завершиться out-of-order. Это что-то доказывает?

Если уж речь зашла о «теоретическом» опыте написания серверов, то, надеюсь, Вас успокоит, что у меня есть чисто практический опыт написания распределенного нагрузочного сетевого теста. Более того, проблема c10k передо мной даже не стояла, потому что была проблема c64k — столько портов доступно на одной системе. Здесь мы можем обсудить преимущества и недостатки самописного менеджмента портов на нескольких IP адресах одного интерфейса против использования wildcard bind в сочетании с SO_PORT_SCALABILITY, а также поговорить о влиянии TIME_WAIT таймаута на количество доступных портов (среди прочего).
После этого, я встану в позу «о чем вообще можно говорить с человеком, который не может с нескольких попыток правильно написать WSARecv» и демонстративно «выйду из дискуссии». Но ведь это же будет контрпродуктивно, не так ли?

не знал что latency увеличится почти в два раза из-за дополнительного системного вызова

И почему тогда Вы обсуждаете то, в чем не разбираетесь?
Latency — это задержка между каким-нибудь событием (в данном случае получением данных) и ответом на него. То, что Вы описали — это задержка самой физической среды, я говорю о задержке уже на самом сервере между получением данных и их обработкой. То есть вместо: «пришли данные — начали обрабатывать» у нас происходит «получили сообщение о том, что пришли данные — запросили данные — начали обрабатывать». Вот это дополнительное «запросили данные» и дает задержку. К тому же там еще и дополнительное копирование, что довольно сильно сказывается уже на 1Gb NIC-ах (у нас есть 10-30 тактов на байт и часть этого времени уже «съедена» другими частями стека, так что тратить оставшиеся такты на ненужное копирование — крайне расточительно, кроме того, тратить лишнюю ~тысячу тактов на каждый пакет — тоже совершенно излишняя роскошь), не говоря уже о 10Gb.

Попробую вернуть обсуждение в оригинальное русло. Чтобы не осталось непонимания, ответьте, пожалуйста, на следующие вопросы:
1. Согласны ли Вы, что если препостить буфер, то можно избежать одного дополнительного копирования и одного дополнительного раундтрипа в ядро на критическом пути (собственно, пути обработки входящих данных)?
2. Если ответ на (1) да, то согласны ли Вы, что это снижает задержку на обработку входящих данных?
3. Согласны ли Вы, что на большинстве современных сетевых карт, достаточно изначально препостить два буфера по 9000 байт (можно даже захардкодить, но лучше спросить драйвер о его MTU) для того, чтобы избежать вышеупомянутого копирования (в то время, как люди перемещают базы данных размером в сотни гигабайт целиком в память, мы пытаемся сэкономить сотню мегабайт даже не физической памяти — а места на диске, задерживая почти в два раза обработку данных, ну да ладно — если это проблема, то ее тоже можно решить)?
4. Согласны ли Вы, что даже если препостить буферы меньшего размера (скажем по 1500 байт), то мы В ХУДШЕМ СЛУЧАЕ выходим на производительность неблокирующего ввода/вывода, при этом в большинстве случаев выигрывая в производительности?
— это асинхронное IO даже не будет работать со всеми ФС в асинхронном режиме, только в тех в которых реализована поддержка

Да, я заметил, что для aio выделены отдельные слоты в vfs. Тем не менее, я все еще прошу цитату из стандарта, что aio предназначен только и исключительно для файловых операций.

мои линуксовые ман файлы говорят: «SO_RCVBUF Sets or gets the maximum socket receive buffer in bytes.»

Да, я сверился как с манами, так и с net/core/sock.c перед тем как постить ответ. Моя цитата — из POSIX:2008.

Опять ваши догадки, я вам говорю как работает на реальных приложениях, а вы опять про какие-то подозрения.

Ну да, догадки. Вы ж так туманно говорите (в случае с WSARead — я «догадался», что Вы имеете в виду, а вот в случае «нулевым буфером» — уж извините, сразу подумал на NULL, а не на zero-length). И да, «в реальных» приложениях так никто не делает. Увеличивать latency почти в два раза (на дополнительный системный вызов) только для того, чтоб «сэкономить» полгигабайта виртуальной памяти (гигабайт места на диске стоит до 30 центов и то только из-за наводнения и если нужен самый дорогой да еще и в ретейле) — причем я исхожу из оценки, которая дана там же. На самом же деле, при том, что максимальный размер TCP пакета 64k — MTU в большинстве реальных условий будет 1.5к (вернее 1500) или 9к. Более того, даже если Вы напишете сервер из расчета на максимальный размер фрейма и этот максимальный размер фрейма Вам таки придет, то максимум, что Вы теряете от того, что не получите весь буфер сразу — это то самое дополнительное копирование из буфера драйвера транспорта в Ваш буфер. Короче, если хочется снижать именно затраты памяти, то постить более двух буферов по 9к не имеет смысла и уже потом можно динамически наращивать исходя из реальной ситуации.

Netmap
NetChannels
итд…

Штуки достаточно интересные, но вообще никаким боком к zero-copy TCP. В одном случае — вообще отказ от TCP, а в другом — оптимизация существующего TCP (что несомненно хорошо и правильно, но лучше использовать В СОЧЕТАНИИ с другими техниками). Без поддержки со стороны железа, zero-copy на прием не сделаешь.

Information

Rating
Does not participate
Registered
Activity