Re: fprintf && write
- From
- Boris Rudakov (2:5054/9.4)
- To
- Andrey Melnikov ()
- Date
- 2003-06-05T11:04:50Z
- Area
- RU.UNIX.PROG
Hello Andrey!
04 июн 03 13:18, you wrote to me:
AM> Hello Boris!
AM> 04 Jun 03 10:57, Boris Rudakov wrote to Andrey Melnikov:
AM>>> Что-то у меня лыжи не едут совсем.
AM>>> Выкидываю все эти fprintf() и заменяю на свою функцию:
[...]
AM>>> static char wr_buf[1024];
BR>> Для теста - прокатит, а вообще стоит избегать глобальных
BR>> переменных. Я нахожу что весь код нужно писать реентерабельным.
BR>> Если нет ОСОБЫХ причин делать иначе :) Я бы этот буфер увеличил
BR>> раза в 4 и засунул внутрь функции
BR>> :)
AM> Дороже выйдет. Войти в процедуру, отрезать кусок стека. Выйти -
AM> подчистить.
Да брось, ты чего ?!
У тебя и так есть локальные переменные - значит стековый кадр в любом случае будет формироваться: на Интелах их слишком много чтобы ограничиться одними регистровыми, да и наличие вложенных вызовов других функций требует где-то сохранять значения на время вызова. Стопудово - стековый кадр будет. Создаетя он (обычно) одним единственым SUB ESP, FrameSize - это один такт :) И какого размера и сколько переменных включает в себя этот FrameSize - похеру. Ты ничего не теряешь.
AM> Код у меня не реентрабельный - задача того не требует.
Эээээээ, ПЛОХАЯ идея :):):):)
Зачем думать над тем применить хороший ход или плохой, но в данном случае безвредный ход, когда можно всегда делать однотипные хорошие ходы ? Зачем в таких случаях напрягать голову раздумьями и рисковать потенциальными багами ?
Лучше всегда оперировать "типично-хорошими" решениями. Реентерабельность - "типично-хорошее" решение.
Через цать времени тебе взбредет эту или аналогичную функцию заюзать в многонитевой программе. Налетишь на грабли. Будешь искать. Найдешь. Будешь материться, перенесешь переменную внутрь функции. Спрашивается - нафига козе баян ? :) Почему сразу же было ее туда не засунуть ?
Писать надо провереными штампами, отдавая предпочтение проверенным и "в общем случае более правильным" ходам.
BR>> 2. Кроме write у тебя есть только один вызов API - select (в
BR>> Виндах я бы сказал "Вызов функции ядра", но думаю что и тут с
BR>> select этот термин будет точен). Морал - тормозит (сверх
BR>> ожидаемого) он.
AM> Наверное - слово тормозит здесь не самое уместное. Я бы сказал -
AM> чаще делиться временем со всеми остальными задачами. Или я неправ ?
Думаю что неправ.
Система работает в режиме вытесняющей многозадачности. Ей похеру что делает твой процесс - вышел квант и амба, пошел работать другой процесс (точнее - нить). Место в котором уснула твоя нить (в своем коде или внутри системного вызова) роли не играет.
BR>> Моя теория такова (еще раз шаркну ножкой что я не юниксоид, но
BR>> основные принципы едины):
BR>> * Твой код делает два системных вызова.
AM> Да. Но без них - у меня два варианта:
AM> 1. Получить засыпание при вызове fprintf(...) где-то в ядре на
AM> write(..) на очень большое время, что увы неприемлимо. 2. Использовать
AM> alarm(time), write()/fprintf(), alarm(0); - я получу 3 системных
AM> вызова.
Давай разберемся чего тебе надо.
1. Если тебе надо просто чего-то вывести в файл (приведенный тобой пример делает это и ничего кроме этого) то сугубо пофигу как ты это делаешь. Есть два варианта:
1.1. Ты вызываешь один блокирующий синхронный вызов (write) и получаешь управлеие назад когда все закончено.
1.1. Ты делаешь асинхроный вызов и потом ждешь когда он завершится.
Вопрос: а нахера ? Какая разница ? Если ты ждешь только завершения IO, то на кой городить огород когда write сделает за тебя это же самое ?!
Я бы понял вариант номер 2:
2. Ты инициируешь асинхронное IO и, параллельно с его работой, делаешь чего-то еще, временами интересуясь как там насчет завершения.
В предыдущей мессаге я как-раз привел подобный код, написанный под НТю с просьбой растусовать как такое делается в юниксах. Там-то задача не просто инициировать IO и дождаться его завершения (тогда мне бы хватило синхронного блокирующего режима ReadFile), но и поймать возможную команду "кансел все нахер" - взведения специального ивента hStopEvent.
Только во втором варианте имеет смысл развлекаться со специальными средствами контроля асинхронных операций IO. В твоем примере такой потребности ну никак не прослеживалось :):):)
Кста, чисто информации для: не знаю как в юниксах, а в НТе многие синхронные операции IO на самом деле - врапперы над асинхронными функциями API. Пример - сокеты. Ядро открывает сокеты всегда в асинхронном и только асинхронном режиме доступа. Если работать с ними основными функциями IO ReadFile/WriteFile, но не передавать структуру OVERLAPPED (она служит для контроля асинхронного IO и если вместо нее подсовывать NULL то это означает что ты желаешь чтобы вызов был блокирующим) то система говорит ERROR_INVALID_PARAMETER - иди, мол, лесом. OVERLAPPED давай. Экспериментально установлено что НТевые реализации send/recv - примитивнейшие врапперы над ReadFile/WriteFile, внутри ожидающие завершения асинхронного IO над сокетами.
Сдается мне что если у тебя нет потребности одновременно с ожиданием завершения асинхронной операции делать чего-то еще, то нет никаких оснований брать на себя задачи синхронизации. Пусть ими занимается API.
У меня, например, в одном из достаточно сложных модулей управления IO (для серверных приложений) со всеми типами файлов, включая сокеты, используются базовые асинхронные средства IO, и никаких врапперов типа синхронных send/recv. Но там у рабочих нитей и задача соотвествующая - ждать не только результатов прокачки данных, но и значительного количества разных управляющих событий.
Ты уверен что у тебя такая же задача и тебе реально нужно чего-то делать одновременно с ожиданием завершения IO ? Из примера следует обратное :)
BR>> Таким образом, сдается мне что двукратное замедление вызвано тем,
BR>> что ты в два раза чаще беспокоишь ядро системы :)
AM> А вот такой вот я плохой - забочусь об состоянии endpoint'a...
В твоем примере нигде не видно двух вещей:
1. Потребности делать что-то параллельно с IO.
2. Потребности прервать IO.
Любой из них достаточно чтобы включать асинхронный режим и вручную контроллировать его завершение.
Если же таких задач не стоит, то нет никаких причин не воспользоваться блокирующим синхронным вызовом.
AM> Andrey aka TEMHOTA-RIPN
Борис Рудаков, Если долго мучиться -
BBR что-нибудь получится !
--- Be happy: BBR is looking at you !
* Origin: АлкАголь малыми дозами безвреден в любых количествах (2:5054/9.4)