Автор Тема: Буферизация ввода/вывода  (Прочитано 26698 раз)

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Буферизация ввода/вывода
« : Январь 16, 2013, 09:35:05 am »
Обсуждение началось здесь: http://forum.oberoncore.ru/viewtopic.php?f=23&t=4214#p77131

Вопрос первый: Есть ли смысл заниматься оптимизацией буферизации I/O на современных жестких дисках в современных осях?
Вопрос второй: Почему в BB буфер имеет фиксированный размер 2 * 1024? Есть ли смысл в другом размере?
Вопрос третий: Есть ли смысл делать буфер под размер кластера? (если нет системного буфера)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #1 : Январь 16, 2013, 09:50:35 am »
Обсуждение началось здесь: http://forum.oberoncore.ru/viewtopic.php?f=23&t=4214#p77131

Вопрос первый: Есть ли смысл заниматься оптимизацией буферизации I/O на современных жестких дисках в современных осях?
Имеет, но только в крайне специфических случаях (например в случае если ты пишешь собственную высоконагруженную СУБД). Скажем в MySQL в случае движка MyISAM все кеширование отдано на откуп ОСи, в случае innodb - кеширование свое. То есть, видимо, когда твой кеш сможет работать эффективней просто потому, что ты точно знаешь паттерн типичных запросов к диску в твоем приложении (а кэш общего назначения естественно заточен под усредненный вероятностный паттерн).

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

Ну и не забываем что у винтов еще свой личноперсональный кэш имеется.

Вопрос второй: Почему в BB буфер имеет фиксированный размер 2 * 1024? Есть ли смысл в другом размере?
Вроде же в исходном топике сказали, что сложилось исторически.

Вопрос третий: Есть ли смысл делать буфер под размер кластера? (если нет системного буфера)
Чтобы избавиться от системного буфера нужно очень специально постараться.

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

Впрочем, зачем рассуждать, если можно просто проверить? Поставь эксперимент и не парься. :-)
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #2 : Январь 16, 2013, 10:28:49 am »
Вопрос второй: Почему в BB буфер имеет фиксированный размер 2 * 1024? Есть ли смысл в другом размере?

В пакете bufio, обеспечивающем в Go буферизированный ввод/вывод дефолтный размер буфера - 4096 байт. Я полагаю это связано не с размером какого-то там кластера на диске, а с размером страницы памяти (4 Кб - пожалуй наиболее частовстречающийся размер страницы). В случае буфера важно обеспечить эффективность распределения и доступа к памяти.

http://golang.org/pkg/bufio/
http://golang.org/src/pkg/bufio/bufio.go
Y = λf.(λx.f (x x)) (λx.f (x x))

pygubanov

  • Newbie
  • *
  • Сообщений: 21
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #3 : Январь 16, 2013, 12:17:21 pm »
по моему, когда скорость ввода кванта данных и скорость вывода кванта данных не равны, то буфер необходим для эффективной работы. Размер же буфера должен определятся конкретной реализацией.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #4 : Январь 16, 2013, 12:32:34 pm »
по моему, когда скорость ввода кванта данных и скорость вывода кванта данных не равны, то буфер необходим для эффективной работы. Размер же буфера должен определятся конкретной реализацией.
Так точно!
И важно понимать, что в данном случае диск совершенно вторичен. Буферизацию собственную делают лишь затем, чтобы поменьше системных вызовов было, а значит и переключений контекста. Системный вызов же какого-нибудь write обычно всего лишь перекладывает данные из нашего буфера в системный.

То есть fflush - это как раз оно, перекладывание данных из памяти приложения в систему.
А вот fsync уже вынудит систему все что есть в буфере положить на диск.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #5 : Январь 16, 2013, 01:24:34 pm »
по моему, когда скорость ввода кванта данных и скорость вывода кванта данных не равны, то буфер необходим для эффективной работы. Размер же буфера должен определятся конкретной реализацией.
Так точно!
И важно понимать, что в данном случае диск совершенно вторичен. Буферизацию собственную делают лишь затем, чтобы поменьше системных вызовов было, а значит и переключений контекста. Системный вызов же какого-нибудь write обычно всего лишь перекладывает данные из нашего буфера в системный.

То есть fflush - это как раз оно, перекладывание данных из памяти приложения в систему.
А вот fsync уже вынудит систему все что есть в буфере положить на диск.

Да, и понятно тогда почему размер буфера делается кратным размеру страницы памяти а не кластеру диска - ведь нам нужно быстро скопировать шмат памяти отсюда туда, а постранично это будет быстрее всего.
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #6 : Январь 16, 2013, 01:49:45 pm »
По поводу 4096 вот тут написано:
http://msdn.microsoft.com/ru-ru/library/windows/desktop/cc644950(v=vs.85).aspx

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #7 : Январь 16, 2013, 01:51:25 pm »
Цитировать
Because buffer addresses for read and write operations must be sector-aligned, the application must have direct control of how these buffers are allocated. One way to sector-align buffers is to use the VirtualAlloc function to allocate the buffers.

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #8 : Январь 16, 2013, 06:58:57 pm »
Код: (stdio.h) [Выделить]
...
/* Buffered I/O macros */

#define BUFSIZ  512

#ifndef _INTERNAL_IFSTRIP_
/*
 * Real default size for stdio buffers
 */
#define _INTERNAL_BUFSIZ    4096
#define _SMALL_BUFSIZ       512
#endif  /* _INTERNAL_IFSTRIP_ */
...
:D

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #9 : Январь 16, 2013, 10:41:25 pm »
По поводу 4096 вот тут написано:
http://msdn.microsoft.com/ru-ru/library/windows/desktop/cc644950(v=vs.85).aspx
Это не тот случай. В bufio никто не полагается на то, что системное кеширование будет отключено.  Также никто не затачивается под винду. Отключение системного дискового кеша это крайне экстремальный случай.

Вопрос - в ББ FILE_FLAG_NO_BUFFERING используется?

Ну и еще раз - буферизация (собственная, на стороне приложения) имеет смысл даже если файл с которым работаем лежит на disk on ram - виртуальном диске в ОЗУ. Потому что сильная экономия на переключении контекстов. Помнишь тормоза в c++ коде в той задачке? Это было ровно из за этого - при чтение и запись было, грубо говоря, не буферизированном. Постоянные системные вызовы. Заметь, что там мой код на c++ ВООБЩЕ с файлами на диске не работал.
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #10 : Январь 17, 2013, 05:47:05 am »
Это не тот случай. В bufio никто не полагается на то, что системное кеширование будет отключено.  Также никто не затачивается под винду. Отключение системного дискового кеша это крайне экстремальный случай.

Вопрос - в ББ FILE_FLAG_NO_BUFFERING используется?
Дисковый кэш никто не отключает. FILE_FLAG_NO_BUFFERING - отключает системный буфер и кэш windows (это позволяет читать/писать асинхронно). В ББ этот флаг не используется.
А вот в MS SQL используется:
Профессиональное руководство по Microsoft SQL Server: структура и реализация

Ничего страшного в отключении системного буфера нет. На Turbo Pascal ведь пользовались блочным вводом/выводом и никто не боялся :)

Ну и еще раз - буферизация (собственная, на стороне приложения) имеет смысл даже если файл с которым работаем лежит на disk on ram - виртуальном диске в ОЗУ. Потому что сильная экономия на переключении контекстов. Помнишь тормоза в c++ коде в той задачке? Это было ровно из за этого - при чтение и запись было, грубо говоря, не буферизированном. Постоянные системные вызовы. Заметь, что там мой код на c++ ВООБЩЕ с файлами на диске не работал.
А я и не спорю с этим  :)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #11 : Январь 17, 2013, 05:54:18 am »
Это не тот случай. В bufio никто не полагается на то, что системное кеширование будет отключено.  Также никто не затачивается под винду. Отключение системного дискового кеша это крайне экстремальный случай.

Вопрос - в ББ FILE_FLAG_NO_BUFFERING используется?
Дисковый кэш никто не отключает. FILE_FLAG_NO_BUFFERING - отключает системный буфер и кэш windows (это позволяет читать/писать асинхронно). В ББ этот флаг не используется.
А вот в MS SQL используется:
Профессиональное руководство по Microsoft SQL Server: структура и реализация

Ничего страшного в отключении системного буфера нет. На Turbo Pascal ведь пользовались блочным вводом/выводом и никто не боялся :)
Я именно про системный дисковый кеш и говорил (я не говорил про кеш самого hdd).
Так вот, отключать его в 99.9% случаев смысла не имеет. Имеет смысл отключать только в о-очень редких случаях (см мой первый пост про MySQL). ББ - это не тот случай когда нужно его отключать.

Какую бы аналогию привести... Ну, вот например: пишешь ты на java, или там на c# каком-нибудь. И берешь, лезешь в рантайм и отключаешь автоматическое включение сборщика мусора, вместо этого сам начинаешь дергать GC тогда когда считаешь что пора уже собирать мусор. Или даже пишешь свой сборщик мусора, и заменяешь им штатный.

На всякий случай еще раз - буферизированный ввод-вывод используется в той же стандартной сишной либе не из за того, что это медленный диск на той стороне, а из за того, что это syscall'ы, число их и минимизируем. Ибо переключение контекстов, а это дорого.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #12 : Январь 17, 2013, 05:57:26 am »
Вот новость в тему: http://www.opennet.ru/opennews/art.shtml?num=35849

Так что с системным кешированием соревноваться смысла нет (и тем более его отключать). Точнее есть смысл в 0.01% задач.
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Буферизация ввода/вывода
« Ответ #13 : Январь 17, 2013, 06:32:50 am »
На всякий случай еще раз - буферизированный ввод-вывод используется в той же стандартной сишной либе не из за того, что это медленный диск на той стороне, а из за того, что это syscall'ы, число их и минимизируем. Ибо переключение контекстов, а это дорого.
А если ты на Си под DOS пишешь?  :)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Буферизация ввода/вывода
« Ответ #14 : Январь 17, 2013, 06:37:40 am »
На всякий случай еще раз - буферизированный ввод-вывод используется в той же стандартной сишной либе не из за того, что это медленный диск на той стороне, а из за того, что это syscall'ы, число их и минимизируем. Ибо переключение контекстов, а это дорого.
А если ты на Си под DOS пишешь?  :)
Так там тоже вроде как через int 21h это делается. Нет? То есть через прерывание - а это медленно. Это рраз.

Два - системный буфер в ДОС-е тоже есть (как бишь эту системную стандартную утиль звали, которая его включает... не помню, надо же... А! Во! smartdrv)
Y = λf.(λx.f (x x)) (λx.f (x x))