Ассинхронный вывод в лог
От: rip_someday Украина  
Дата: 18.04.06 13:18
Оценка:
В общем стоит передо мной такая задача

Дано:

однопоточный программный продукт весьма активной сетевой работой
работает через обертку вокруг epoll
программа ресурсоемкая и в то же время в больших объемах пишет лог файлы в формате CSV (несколько штук)
то есть размер буффера для единичной операции записи — строка 200-250 байт
таргет платформа — linux Fedora Core 4

Нужно:

проанализировать подходы к эффективной запись в лог-файлы
в том числе с использованием асинхронной записи.
Лично мне кажется, что замена текущей (весьма медленной и корявой) имплементации "fopen-fwrite-fclose на каждую строку"
на имплементацию с постоянно открытым файлом, буффером в ~64Кб и периодическим сбросом на диск вполне будет достаточно
(по крайней мере судя по замерам — в 30-40 раз быстрее)
Но для очистки совести и успокоения начальства, надо протеститровать и асинхронную работу.

Собственно возникают вопросы:
1. каким образом это можно (нужно) организовать?
2. нашел упоминание о поддержке aio на уровне ядра в ядрах 2.6.х, но к сожалению не нашел вразумительной информации об этом. Работает ли это вообще? какие есть подводные камни?
3. можно ли это сделать как-то иначе?

буду благодарен если в меня бросят ссылкой с более или менее подробной информацией по эьтому вопросу.
Re: Ассинхронный вывод в лог
От: zaufi Земля  
Дата: 19.04.06 21:57
Оценка: +1
Здравствуйте, rip_someday, Вы писали:

_>Нужно:


_>проанализировать подходы к эффективной запись в лог-файлы

_>в том числе с использованием асинхронной записи.
_>Лично мне кажется, что замена текущей (весьма медленной и корявой) имплементации "fopen-fwrite-fclose на каждую строку"
_>на имплементацию с постоянно открытым файлом, буффером в ~64Кб и периодическим сбросом на диск вполне будет достаточно
_>(по крайней мере судя по замерам — в 30-40 раз быстрее)

Адназначна ДА! Делать окрытие файлов для записи строки в лог это УЖОС! Конечно же файлы нада держать вседа открытыми! Правда в случае fopen/fwrite/fclose делать свой буфер не есь хорошо... он уже там есть (и его размером мона поиграца еси я все прально помню из info по libc)! Собственный буфер имеет смысл при low level I/O -- open/write/close... и лучше его сделать побольше! -- порядка 1.5М (зависит конечно от скорости заполнения буфера и того насколько страшно потерять нефлашеный лог в случае непредвиденных обстоятельств -- но основной смысл в том что писать нада риальна МНОГО -- контроллеры винчей порой имеют кэш 8 и более М -- нет повода стеснять себя килобайтами...

_>Но для очистки совести и успокоения начальства, надо протеститровать и асинхронную работу.

давным давно (када дизайнилась одна мега прога тоже пишущая на диск гигабайтами всяких данных) я почитал про это и решил забить -- точной причины не вспомню... но тяжелый осадок от прочтения остался -- толи там недоделано чивота, толи черезчур сложно... не помню

НО есть разхумееца другой выход! -- см. ниже

_>Собственно возникают вопросы:

_>1. каким образом это можно (нужно) организовать?
_>2. нашел упоминание о поддержке aio на уровне ядра в ядрах 2.6.х, но к сожалению не нашел вразумительной информации об этом. Работает ли это вообще? какие есть подводные камни?
_>3. можно ли это сделать как-то иначе?

конечно! оставь работу с логами на долю того кто под это заточен! -- а имена syslog демон
означеная мегапрога генерила порядка 1Г (или даже больше -- точную цыфру не вспомню -- но РИАЛЬНА ДОФИГА) зипаных логов в день -- не все сислоги такое выдерживают.. но есь один который более менее работал в подобных условиях -- это был syslogng

твоя задача используя функцию syslog(3) писать все что тебе там хочеца в ОДИН источник -- пусь syslogовские фильтры позднее потом разбираются чо куда распихивать и как ротейтить... -- возможно даже передавать это куданить на специально выделенный сервер (как вот было у нас в кластере -- ибо спамить хотели многие демоны а лазить по куче тачек грепать ихние логи абломно)

для упрощения работы мона сделать iostreamный syslog класс -- буишь стрелочками фигачить себе в syslog и не парица



_>буду благодарен если в меня бросят ссылкой с более или менее подробной информацией по эьтому вопросу.
Re: Ассинхронный вывод в лог
От: Dair Россия  
Дата: 19.04.06 22:13
Оценка:
Я бы делал по отдельному процессу (или треду, дело вкуса) под каждый записываемый файл, общался бы через fifo.

Запись тоже производил бы через poll/select, буферизуя входящие данные (так можно управлять размером этого буфера).
Никаких iostream/stdio, только open/write/close. open, понятно, один раз, close тоже, посередине пользоваться, например, fdatasync.
Re[2]: Ассинхронный вывод в лог
От: zaufi Земля  
Дата: 20.04.06 08:52
Оценка:
Здравствуйте, Dair, Вы писали:

D>Я бы делал по отдельному процессу (или треду, дело вкуса) под каждый записываемый файл, общался бы через fifo.


а я бы не стал так делать -- врядли скорость постепления логерских строк такова что эти threadы будут работать без простоев...
IMHO достаточно одного thread'a который буит владеть буферами и открытыми файлами и флашить на диск переполненные буферы (либо по таймауту -- ибо еси в буфер ничо не поступает и он не полный его тоже нада както записать

D>Запись тоже производил бы через poll/select, буферизуя входящие данные (так можно управлять размером этого буфера).


IMHO не нада усложнять себе жысть играми с неблокирующимся I/O... write(buffer, 1.5M); буит вполне достаточно!

D>Никаких iostream/stdio, только open/write/close. open, понятно, один раз, close тоже, посередине пользоваться, например, fdatasync.


IMHO выбор за тобой -- избавившись от постоянного открытия файлов у тя все буит "летать"! дальнейшие оптимизации нада делать _только_ на основании профайлерных данных -- не нада бежать впереди поезда...

PS: персонально мой солюшин былбы в использовании syslog...
Re[2]: Ассинхронный вывод в лог
От: rip_someday Украина  
Дата: 20.04.06 09:50
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, rip_someday, Вы писали:


_>>Нужно:


_>>проанализировать подходы к эффективной запись в лог-файлы

_>>в том числе с использованием асинхронной записи.
_>>Лично мне кажется, что замена текущей (весьма медленной и корявой) имплементации "fopen-fwrite-fclose на каждую строку"
_>>на имплементацию с постоянно открытым файлом, буффером в ~64Кб и периодическим сбросом на диск вполне будет достаточно
_>>(по крайней мере судя по замерам — в 30-40 раз быстрее)

Z>Адназначна ДА! Делать окрытие файлов для записи строки в лог это УЖОС! Конечно же файлы нада держать вседа открытыми! Правда в случае fopen/fwrite/fclose делать свой буфер не есь хорошо... он уже там есть (и его размером мона поиграца еси я все прально помню из info по libc)! Собственный буфер имеет смысл при low level I/O -- open/write/close...


я так и сделал, ну не совсем же я дурак все-таки

Z> и лучше его сделать побольше! -- порядка 1.5М (зависит конечно от скорости заполнения буфера и того насколько страшно потерять нефлашеный лог в случае непредвиденных обстоятельств -- но основной смысл в том что писать нада риальна МНОГО -- контроллеры винчей порой имеют кэш 8 и более М -- нет повода стеснять себя килобайтами...


в принципе размер буффера можно подобрать потом, даже лучше сделать конфигурируемым.

_>>3. можно ли это сделать как-то иначе?


Z>конечно! оставь работу с логами на долю того кто под это заточен! -- а имена syslog демон

Z>означеная мегапрога генерила порядка 1Г (или даже больше -- точную цыфру не вспомню -- но РИАЛЬНА ДОФИГА) зипаных логов в день -- не все сислоги такое выдерживают.. но есь один который более менее работал в подобных условиях -- это был syslogng

спасибо за идею, возможно имеет смысл.
кстати необходимая интенсивность записи может измеряться сотнями метров в час.
Re[3]: Ассинхронный вывод в лог
От: Аноним  
Дата: 20.04.06 11:01
Оценка:
Здравствуйте, rip_someday, Вы писали:


_>спасибо за идею, возможно имеет смысл.

_>кстати необходимая интенсивность записи может измеряться сотнями метров в час.

Yea! тада и думать вопчем не чиво ! -- syslog the best way!
Re: Ассинхронный вывод в лог
От: MaximE Великобритания  
Дата: 22.04.06 08:48
Оценка: +1
rip_someday wrote:

> В общем стоит передо мной такая задача

>
> Дано:
>
> однопоточный программный продукт весьма активной сетевой работой
> работает через обертку вокруг epoll
> программа ресурсоемкая и в то же время в больших объемах пишет лог файлы
> в формате CSV (несколько штук)
> то есть размер буффера для единичной операции записи — строка 200-250 байт
> таргет платформа — linux Fedora Core 4
>
> Нужно:
>
> проанализировать подходы к эффективной запись в лог-файлы
> в том числе с использованием асинхронной записи.
> Лично мне кажется, что замена текущей (весьма медленной и корявой)
> имплементации "fopen-fwrite-fclose на каждую строку"
> на имплементацию с постоянно открытым файлом, буффером в ~64Кб и
> периодическим сбросом на диск вполне будет достаточно
> (по крайней мере судя по замерам — в 30-40 раз быстрее)
> Но для очистки совести и успокоения начальства, надо протеститровать и
> асинхронную работу.
>
> Собственно возникают вопросы:
> 1. каким образом это можно (нужно) организовать?
> 2. нашел упоминание о поддержке aio на уровне ядра в ядрах 2.6.х, но к
> сожалению не нашел вразумительной информации об этом. Работает ли это
> вообще? какие есть подводные камни?
> 3. можно ли это сделать как-то иначе?

Твой IO поток не должен блокироваться, поэтому, на мой взгляд, хорошим решением
будет circular buffer, как у printk. Т.е. IO поток сбрасывает строки в
циклический буфер в память, никогда при этом не блокируясь, и сигнализирует этот
факт подходящим механизмом межпотокового взаимодействия (например,
semaphore.release()). Другой поток или лучше другой процесс тупо в блокирующем
режиме пишет данные из циклического буфера на диск или ждет на семафоре, когда
писать нечего. Если буфер находится в shared memory и запись производится другим
процессом, даже если процесс, который пишет в буфер, погибает, другой процесс
запишет в файл все, что записал в память погибший процесс.

Если потоков всего два: один пишет в буфер, другой читает, то можно сделать
буфер вообще lock free.

--
Maxim Yegorushkin
Posted via RSDN NNTP Server 2.0
Re[2]: Ассинхронный вывод в лог
От: Андрей Коростелев Голландия http://www.korostelev.net/
Дата: 22.04.06 11:12
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Твой IO поток не должен блокироваться, поэтому, на мой взгляд, хорошим решением

ME>будет circular buffer, как у printk. Т.е. IO поток сбрасывает строки в
ME>циклический буфер в память, никогда при этом не блокируясь, и сигнализирует этот
ME>факт подходящим механизмом межпотокового взаимодействия.

+1
Добавлю что, так как IO поток не должен блокироваться, его размер должен быть достаточен, чтобы свести количество выделений памяти для увеличения буфера при его полном заполнени.
-- Андрей
Re[3]: Ассинхронный вывод в лог
От: MaximE Великобритания  
Дата: 22.04.06 13:11
Оценка:
Здравствуйте, Андрей Коростелев, Вы писали:

АК>Здравствуйте, MaximE, Вы писали:


ME>>Твой IO поток не должен блокироваться, поэтому, на мой взгляд, хорошим решением

ME>>будет circular buffer, как у printk. Т.е. IO поток сбрасывает строки в
ME>>циклический буфер в память, никогда при этом не блокируясь, и сигнализирует этот
ME>>факт подходящим механизмом межпотокового взаимодействия.

АК>+1

АК>Добавлю что, так как IO поток не должен блокироваться, его размер должен быть достаточен, чтобы свести количество выделений памяти для увеличения буфера при его полном заполнени.

Я предлагаю выделять память под циклический буфер лишь однажды (как это сделано в ядре линукс). Если поток, пишущий на диск не поспевает, старые записи в буфере будут затираться новыми.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.