ПрограммированиеФорумОбщее

Ведение лог файла (4 стр)

Страницы: 1 2 3 4
#45
21:13, 5 янв 2010

имхо по-уму система логгирования (так же как и система генерации дампов и прочие неубиваемые сервисы) должна висеть в отдельном процессе.

#46
21:17, 5 янв 2010

Sayron
> Конишуа, а обычное STL'овское write скидывает данные в буффер ядра или пишет
> прямо на диск
Iostream-ы открывают файл в режиме буферизации в ядре.
Кроме того, в самом объекте stream есть буфер.
То есть данные сначала попадают в пользовательский буфер, откуда отсылаются в ядро по достижению некоторой критической массы.
А ядро физически запишет данные на диск когда ему будет это удобно.

Чтобы сбросить пользовательский буфер в stream-е есть метод flush.
Также сброс буфера происходит при выводе в поток объекта std::endl.

Stdio в части буферизации полностью идентична.

Sayron
> Чем плохо скидывание в системный буффер строк из нескольких потоков
> одновременно?
Внутри стрима нет синхронизации, все упадет.
Кстати олдскульный FILE можно безопасно использовать из нескольких тредов одновременно.

Edit: поправил тэги.

#47
21:26, 5 янв 2010

Sayron
> Сейчас скину свою реализацию, которая НЕ РАБОТАЕТ при падении программы.
Добавь flush после write.

#48
21:31, 5 янв 2010

JokerR, поясните свою мысль пожалуйста.
Как вести логи в мультипотоковом приложении.

Вот допустим я имею несколько потоков
1 - поток для рендера
2 - поток обсчета Аи
3 - под музыку

Как при этом (в общих чертах) ведутся логи?

#49
21:32, 5 янв 2010

Sayron
> Как при этом (в общих чертах) ведутся логи?
В разные файлы?

#50
21:35, 5 янв 2010

Нет-нет... Просто допустим как должен блок АИ формировать логи (куда писать) если потоки параллельны?

#51
21:35, 5 янв 2010

Щас я кратко постараюсь написать как я собираюсь делать двиг мультипотоковым.

#52
21:39, 5 янв 2010

Значит есть у нас 3 потока -
1 - Поток для создания того, что будет отправляться в видеопамять.
2 - обсчет АИ по данным.
3 - поток под музыку.
1 и 3-ий потоки используют данные, подготовленные вторым потоком.
Во время критической секции у нас происходит следующее.
АИ-поток формирует буфер данных для потоков 1 и 3 (делает снимок необходимых данных).
Соответственно во время параллельного выполнения ни один поток не лезет к другому в память.
Вот мне и интересно - каким образом формировать поток логов?

#53
21:43, 5 янв 2010

Sayron
> Во время критической секции у нас происходит следующее.
Если тебе знаком термин критическая секция, почему возникают вопросы как синхронизировать доступ к логу из нескольких параллельных тредов?

#54
21:45, 5 янв 2010

Допустим во время параллельного исполнения блок АИ падает. Как при этом сохранить логи?

#55
21:52, 5 янв 2010

Мне термин известен в теории...
На этой неделе у меня сверхзадача - доделать генератор карт (и я его походу доделаю).
Следующей стадией стоит задача сделать свой однопотоковый движок мультипотоковым (на основе директив openMP), поскольку игра будет представлять собой варгейм аля Европа 3 и на обсчет АИ там хватит только нескольких реальных секунд. Поскольку АИ будет довольно таки сложным (и делаться на основе обсчетов векторов STL), то вылеты во время отладки неизбежны.
А поскольку я свой генератор карты делаю уже почти год (и знаю, что у меня в коде бывают как тупые ошибки, так и очень-очень глубоко зарытые, всплывающие раз в месяц под знаком всемогущего рандома), то требуется вести отладку логами.
Как ты понимаешь - сохранение логов при этом глобальная задача, резко ускоряющая отладку кода и работу над проектом в целом.

#56
23:22, 5 янв 2010

Sayron
> Допустим во время параллельного исполнения блок АИ падает. Как при этом
> сохранить логи?
Технически это выглядит как-то так.
Тред, в котором исполнялся упавший код ловит необработанное исключение в UnhandledExceptionFilter.
В это время другие треды продолжают работать.
Фильтр входит в критическую секцию, которая охраняет лог (потому что другие треды продолжают работать).
Сбрасываются все буферизованные строки.
После этого фильтр возвращает EXCEPTION_CONTINUE_SEARCH, что приводит к появлению стандартного окна с предложением отправить отчет в Microsoft или подключить отладчик, и в конечном счете, к завершению процесса.

Какие тут есть подводные камни?

Все это маловероятно, но теоретически возможно.

Я бы не пытался оптимизировать до тех пор, пока все не упрется в производительность лога, и сделал бы попроще.
Одна запись в логе - один вызов ядра, нет необходимости сбрасывать буфера при сбое.
Делал бы тупо через stdio (потому что вызовы из разных тредов автоматически синхронизируются).

#57
23:53, 5 янв 2010

Конишуа
То есть, по сути ты предлагаешь сделать следующим образом. В общем виде:
У каждого потока есть свой лог-файл, в который они сбрасывают данные. Как только поток дал сбой - stdio как я понимаю, ВСЕ открытые через него файлы закрывает, и мы сохраняем логи на момент падения потока.
Таким образом никакого отдельного потока под логи нет, а система сброса данных записи в ядро все синхронизирует сама (то есть если один поток скидывает данные в свой файл одновременно с другим, то все будет нормально и библиотека stdio, т.о. потокобезопасна? )

#58
1:55, 6 янв 2010

Sayron
Да нет же.

Есть объект, один на все приложение, через который пишутся логи.
Как пример - тупо FILE из stdio.
Библиотека stdio синхронизует доступ к своим объектам из нескольких тредов одновременно.
С каждым объектом FILE связана своя критическая секция (КС).
Каждый метод, например fprintf(), захватывает эту КС на время своей работы.
Таким образом, можно без проблем вызывать fprintf() из разных тредов над одним и тем же объектом FILE.
В отличие от std::ostream, для которой потокобезопасность не гарантируется.

То есть лог файл - он один, на все треды.

Идем дальше.

У объекта FILE есть свой собственный буфер, который находится в памяти приложения.
Данные в нем накапливаются, а затем доставляются в ядро ОС системным вызовом write (Linux) или WriteFile (Win).
Так вот, этот буфер надо сбрасывать в момент сбоя.
Я предлагаю сбрасывать буфер после каждой записи в лог (функцией fflush или как-то еще).
Тем самым, гарантируется что в момент сбоя буфер пуст, и ничего делать не надо.

И если потом окажется что частый fflush() тормозит (не верю), можно будет перенести fflush() в обработчик неперехваченных исключений (установленный SetUnhandledExceptionFilter).

#59
5:59, 6 янв 2010

Ну все - наконец-то дошло!
Огромное спасибо за проявленное старание во вдалбливание материала в мою не С-шную голову!!!

Буду пробовать

Страницы: 1 2 3 4
ПрограммированиеФорумОбщее

Тема в архиве.