fprintf && write
- From
- Andrey Melnikov (2:5030/1340.116)
- To
- Lev Walkin ()
- Date
- 2003-06-05T17:27:26Z
- Area
- RU.UNIX.PROG
Hello Lev!
05 Jun 03 00:49, Lev Walkin wrote to Andrey Melnikov:
LW> Andrey Melnikov wrote:
>> AM>> Выкидываю все эти fprintf() и заменяю на свою функцию:
>>
>> AM>> static char wr_buf[1024];
>>
>> BR> Для теста - прокатит, а вообще стоит избегать глобальных
>> BR> переменных. Я нахожу что весь код нужно писать реентерабельным.
>> BR> Если нет ОСОБЫХ причин делать иначе :) Я бы этот буфер увеличил
>> BR> раза в 4 и засунул внутрь функции :)
>> Дороже выйдет. Войти в процедуру, отрезать кусок стека. Выйти -
>> подчистить. Код у меня не реентрабельный - задача того не требует.
LW> Что это за бред? Процедура отрезания куска стека НЕ занимает
LW> дополнительного времени. Процедура подчистки стека НЕ занимает
LW> дополнительного времени.
Только за счет того, что gcc не использует пару enter/leave. Но как только я захочу заливать этот буфер нулями при создании - мне там нарисуют кучу кода, который на мои 324 тысячи вызовов будет уже довольно дорог.
LW> Мало того, из-за того, что стек постоянно используется, он будет в
LW> кеше процессора, а значит и программы с данными на стеке будут
LW> выполняться в среднем быстрее.
Первый попавшийся context switching отправит этот кэш куда подальше. И программы с данными на стеке - заведомо медленней из-за большего количесва пересчетов адресов (на этой пресловутой i386 архитектуре с ее страницами, таск-гейтами и прочей чехардой).
LW> Не тогда, когда ты их крутишь в цикле for(), чтобы проверить
LW> быстродействие, а тогда, когда этот кусок кода используется в
LW> реальных (больших) программах.
LW> Тогда возникнет интересный момент: скопище "быстрых" участков кода
LW> становится программой, которая работает медленнее, чем аналогичная,
LW> у которой соответствующие кусочки значительно медленнее.
>> BR> 2. Кроме write у тебя есть только один вызов API - select (в Виндах
>> BR> я бы сказал "Вызов функции ядра", но думаю что и тут с select этот
>> BR> термин будет точен). Морал - тормозит (сверх ожидаемого) он.
>> Наверное - слово тормозит здесь не самое уместное. Я бы сказал -
>> чаще делиться временем со всеми остальными задачами. Или я неправ ?
LW> Скорее, тратится время в ядре на проверку аргументов и исполнения
LW> алгоритма системного вызова.
>> BR> Моя теория такова (еще раз шаркну ножкой что я не юниксоид, но
>> BR> основные принципы едины):
>>
>> BR> * Твой код делает два системных вызова.
>> Да. Но без них - у меня два варианта:
>>
>> 1. Получить засыпание при вызове fprintf(...) где-то в ядре на write(..)
>> на очень большое время, что увы неприемлимо. 2. Использовать
>> alarm(time), write()/fprintf(), alarm(0); - я получу 3 системных вызова.
LW> а попробуй так:
LW> 1. при открытии дескриптора переводи его в non-blocking mode.
LW> 2. В подобных твоему участках кода делай _сначала_ write(), а уж потом,
LW> если write() вернул -1/EAGAIN, то select:
LW> while() {
LW> if(write()) {
LW> select();
LW> ...
LW> }
LW> }
LW> Тогда имеется вероятность, что за один вызов write() управишься в
LW> большом количестве случаев.
Вот это уже похоже на правду. Ушел пробовать.
Andrey aka TEMHOTA-RIPN
--- GoldED+/LNX 1.1.4.7
* Origin: Powered by SlackWare Linux (2:5030/1340.116)