LINUX.ORG.RU

printf, буферизация и heavy I/O

 , , ,


1

1

Пишу на Си не суть важно что, но это что-то читает блочное устройство в цикле по 512 байт за раз (по размеру блока). Т.к. блочное устройство — SSD, скорость чтения большая (~300–400 МиБ в секунду, подтверждается через IO_RATE в htop'е).

Допустим, я хочу каждую секунду выводить значение текущей скорости чтения. Раз в 1000 циклов чтения проверяю, прошла ли секунда, если да, то пишу статистику в консоль через printf.

Проблема в том, что это не работает. Точнее, работает, но с задержкой в 7–8 секунд. Если инфу выводить не через printf, а форматить вручную и писать через write(STDOUT_FILENO, buf, strlen(buf)), то всё выводится, как и нужно. Если после printf делать fflush(stdout), то тоже работает.

Собственно, два вопроса:

  1. правильно ли я понимаю, что это из-за буферизации вывода через printf?
  2. связано ли это с 12309?

А не проще сообщения отправлять или ещё как через IPC? Например в общей памяти счётчик инкрементировать.

На таких циклах накладные расходы на силовую отладку слишком велики. Пусть отдельный процесс считывает инфу. В смысле в основном процессе никаких «каждые 100 циклов». А второй процес инициирует получение инфы.

ziemin ★★
()
Последнее исправление: ziemin (всего исправлений: 1)

1. да

2. нет

каждую секунду выводить значение текущей скорости чтения. Раз в 1000 циклов чтения проверяю, прошла ли секунда, если да, то пишу статистику в консоль

знатный изврат

MKuznetsov ★★★★★
()
Ответ на: комментарий от ziemin

Совет дельный, конечно, спасибо, но в первую очередь интересует, почему дисковый ввод-вывод так влияет на консольный.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от ziemin

В проц не упирается, процентов 70 максимум на всё. На одном ядре, но CFS периодически перебрасывает с одного ядра на другое.

post-factum ★★★★★
() автор топика

Если я правильно понял тебе надо setbuff(stdout,NULL); Тоесть отключить буферизацию вывода, это часто приходится делать если например нужно в консоли не просто вывести строку, а дописывать её. И да буферизация в stdout/stdin есть.

Dron ★★★★★
()
Ответ на: комментарий от val-amart

Зато вводит в заблуждение иногда.

Dron ★★★★★
()
Ответ на: комментарий от post-factum

Попробуй профилировать. В смысле сам вывод инфы. Ну или вынеси всё-таки в отдельный поток. Мне кажется у тебя более серьёзные задачи чем выяснение почему сообщения задерживаются.

ziemin ★★
()
Ответ на: комментарий от anonymous

Повторю специально для анонимуса - с тем, что буферизация есть, разобрались, как фиксить - тоже, осталось понять влияние дискового IO.

post-factum ★★★★★
() автор топика
Ответ на: комментарий от post-factum

на вопрос о лагах буферизации не отвечает

То есть отсутствие сброса буфера печати не отвечает на вопрос о лагах буферизации? Ну окей.

tailgunner ★★★★★
()
Ответ на: комментарий от post-factum

Почему при интенсивном дисковом IO консольный буфер сбрасывается чёрти-когда?

Я не могу тебе ответить в терминах дискового IO, потому что не знаю, причастен ли он к проблеме. Прикола ради замени чтения на тупые паузы.

tailgunner ★★★★★
()
Ответ на: комментарий от post-factum

Хорошо, почему без дискового ввода-вывода printf сразу выводит строку, а не через 7 секунд?

как ты то определил? покажи код, который демонстрирует моментальный вывод и код который демонстрирует 7-ми секундную задержку. вангую что если ты ио в цикле заменишь просто на слипы, ты увидишь что вивод на экран все-равно с задержкой.

val-amart ★★★★★
()

Допустим, я хочу каждую секунду выводить значение текущей скорости чтения. Раз в 1000 циклов чтения проверяю, прошла ли секунда, если да, то пишу статистику в консоль через printf.

Может быть это лучше делать в отдельном потоке?

Deleted
()

А чего ты просто write в stdout не делаешь?

Ну или отключи буферизацию setbuf'ом.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от post-factum

почему дисковый ввод-вывод так влияет на консольный

Кстати, да: даже с твоими патчиками все равно при интенсивном дисковом вводе-выводе тормозит все! Потребление процессора под 0, а тормоза несусветные. Похоже, таки от 12309 нам не избавиться никогда!

Я даже как-то подвешивал компьютер до такой стадии, что sysrq не работало!

Eddy_Em ☆☆☆☆☆
()

У SSD размер блока 4К, даже если он притворяется будто 512B.

rand
()

Линукс тут при чём?

anonymous
()
Ответ на: комментарий от post-factum

а размер выводимых через printf данных так мал что буфер заполнялся только за 7 секунд? я просто сначала подумал что вывод серез printf интенсивный

quest ★★★★
()

правильно ли я понимаю, что это из-за буферизации вывода через printf?

да, а что тебя удивило?

связано ли это с 12309?

это всю жизнь так было.

emulek
()
Ответ на: комментарий от post-factum

но в первую очередь интересует, почему дисковый ввод-вывод так влияет на консольный.

собственно там один и тот же ввод/вывод.

emulek
()
Ответ на: комментарий от emulek

Емулек такой емулек. Тред не читай, просто отвечай.

А принтф у него сразу выводил скорее всего потому завершался тестовый процесс.

staseg ★★★★★
()
Ответ на: комментарий от staseg

Тред не читай, просто отвечай.

дык так оно и было: буфер не сбрасывал, он сам и не сбрасывался. Точнее сбрасывался хрен знает когда. Это нормальное поведение, я его наблюдал. И если загрузить систему IO, то это «хрен знает когда» наступает намного позже.

А принтф у него сразу выводил скорее всего потому завершался тестовый процесс.

не, если загрузить систему одним printf, которое НЕ сбрасывает буфер, то это «хрен знает когда» наступает сразу.

Можешь проверить ещё и на fputc, записывая в любой файл любые данные. Он же по чуть-чуть писал, а буфер в FILE ЕМНИП 65К. И сам он сбрасывается лишь когда переполнится. Да, в консоли можно ещё выводить tail -f | sed ". (в sed есть --unbuffered для того, что-бы сразу).

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.