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)