среда, 3 марта 2010 г.

endl effect

При разработке часто используют вывод отладочной информации в лог файлы. В простейшем случае это может выглядеть вот так:
ofstream_log_file_ << 
  "Add useful debug message here " << 
  extra_info_ << std::endl;
В этом коде вызывается функция std::endl, которая помимо перевода строки для буферезированных потоков сбрасывает буфер в выходной файл. При небольшом количестве таких вызовов это даже полезно — в случае падения программы в логе останется полезная информация. Но для интенсивного логгирования, когда нужно писать в лог очень часто, эта дополнительная особенность снижает скорость в несчитанное количество раз.

Ускорить запись в лог очень просто — меняем std::endl на известный символ "\n".
ofstream_log_file_ << 
  "Add useful debug message here " << 
  extra_info_ << "\n";

9 комментариев:

  1. Не понимаю смысл лога который при падении приложения не сохранит последние сообщения :) Если уж действительно встал вопрос быстродействия, что маловероятно, то решать его можно другими методами, например отправкой сообщений другому процессу который будет их ставить в очередь и сбрасывать на диск.

    ОтветитьУдалить
  2. Лог нужен не только, если что-то падает. А так получается самый быстрый и простой вариант.

    ОтветитьУдалить
  3. "Быстрый" в плане потраченных на реализацию сил.

    ОтветитьУдалить
  4. ИМХО, одним из самых правильных способов - это логгирование в syslog. Пишем простой враппер, чтобы можно было писать код вида:

    LOG( L_DEBUG ) << " bla-bla-bla " << endl;

    и внутри все перенаправляем в сокет syslog-а.
    В результате получаем и отложенное логгирование, и не будет потери сообщений при аварийном завершении.

    ОтветитьУдалить
  5. Не нужно забывать, что не на всех платформах есть syslog(или даже сокеты). А свои реализации писать порой слишком накладно.

    ОтветитьУдалить
  6. std::endl кроме всего прочего будет вставлять \r\n на одной платформе и \n на другой.

    ОтветитьУдалить
  7. std::endl вставляет на всех платформах \n. А вот во что преобразуется \n — это определяется реализацией.

    ОтветитьУдалить
  8. Т.е. \n в конечном виде может преобразоваться реализацией в CR LF (0D 0A) или в LF CR (0A 0D) или ещё во что-то.

    Ещё см. стандарт 27.6.2.7: результат endl есть os.put(os.widen(’\n’) ), then os.flush().

    ОтветитьУдалить
  9. 2jia3ep: проверил, действительно, вы правы!
    "\n" на Windows тоже пишется как 0D0A . Тогда беру свои слова обратно. Записи равнозначные.

    ОтветитьУдалить