LINUX.ORG.RU

Эффективное параллельное чтение большого числа файлов

 


1

3

Возник насущный вопрос: как разные http- и ftp-серверы решают проблему эффективного одновременного, последовательного для каждого отдельного файла, чтения большого числа файлов? Ведь скорость последовательного чтения у HDD может превосходить скорость произвольного доступа на 2 порядка и более, и если много клиентов одновременно запрашивают много файлов, то узким местом становится дисковая подсистема, а не сеть или CPU. Вместо сотен мегабайт в секунду получаются сотни килобайт. Мне интересно существует ли проверенное кросплатформенное решение для c++, которое бы организовывало эффективное кэширование и сериализацию чтения для такого случая? Идеи для собственного велосипеда имеются, но зачем его изобретать, если вдруг он уже есть? Стандартный ifstream как-то не очень справляется, особенно на оффтопике. Даже установка буфера в несколько мегабайт не помогает.

★★★★★

Этим эффективно занимается операционная система: есть дисковый кэш, есть планировщик ввода/вывода, есть NCQ и read-ahead, в конце концов.

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

Откуда операционная система знает нужен мне read-ahead или нет? Потому что если он мне не нужен, то тогда он может быть просто вреден.

asaw ★★★★★
() автор топика

Читай файлы бОльшими блоками. Используй mmap.

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

Это уже не операционная система знает, а контроллер диска. Конкретный механизм не ведаю, увы.

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

По-умолчанию считает, что нужен. Для настройки этого есть posix_fadvise() и флаги для CreateFile() на оффтопике.

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

Да. В оффтопике в сишном интерфейсе стандартной библиотеки файл можно открыть с флагом _O_SEQUENTIAL, но для std::ifstream такого аналога нет. Вопрос: как убедиться что std::ifstream открывается с этим флагом или с его аналогом?

asaw ★★★★★
() автор топика
Последнее исправление: asaw (всего исправлений: 1)
Ответ на: комментарий от xaizek

Это понятно. Меня интересует кроссплатформенный интерфейс вроде std::fstream. Потому что иначе придется изобретать велосипед.

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

DMA и так целыми секторами читает, хочешь ты этого или нет, плюс это всё хранится в кэше. Не нужны никакие велосипеды, это рабочий workflow.

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

Меня интересует кроссплатформенный интерфейс вроде std::fstream

Кроссплатформенный интерфейс не может знать и уметь все особенности различных платформ. Максимум как в QFile - уметь работать поверх уже открытого FILE* или fd.

http://doc.qt.io/qt-5/qfile.html#open-2

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

Вопрос именно про кэш, а конкретнее - про стратегию кэширования для данной конкретной задачи. Нужно чтобы ОС делала вот это:

Читай файлы бОльшими блоками.

Потому что по умолчанию она этого НЕ делает.

asaw ★★★★★
() автор топика

Ведь скорость последовательного чтения у HDD может превосходить скорость произвольного доступа на 2 порядка и более

Для этого в системе есть планировщик I/O

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

В std::fstream всегда можно подсунуть кастомный streambuf, который работает поверх fd/FILE/HANDLE (вроде, можно использовать file_descriptor + stream из Boost для этой цели, тогда будет без ifdef'ов).

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

Ну то есть без велосипедостроения никак?

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

anonymous
()

как разные http- и ftp-серверы решают проблему эффективного одновременного

А с чего ты вообще взял, что они что-то там решают? Это такие афигенные куллстори.

последовательного для каждого отдельного файла, чтения большого числа файлов?

Файлов мало - все они живут всегда в кеше - никаких проблем. Если у тебя что-то не влезает - это уже твои проблемы - это уже совершенно иной мир.

Вместо сотен мегабайт в секунду получаются сотни килобайт

А с чего ты взял, что там нужны какие-то сотни мегабайт? Где такое есть?

Дефолтный хард - это 100ипосов - это 4к * 100 - пол метра трупута для 100юзеров. Реально 100юзеров никогда на одной тачке не сидят, а где сидят - там не стоит днище с соткой ипосов.

Обычно никто так идеально всех не шеддулит и хапают они больше, чем дефолтный пейджкеш.

Поэтому типичная ситуация - 10юзверей на днищетачке может в 4метра рандомных ридов по 4к. Это уже половина канала дефолтной домохозяйки.

Мне интересно существует ли проверенное кросплатформенное решение для c++

Посмеялся. Ничего не кросплатформенного такого уровня, да и вообще ничего нет. Если ты хочешь какую-то днищеобёртку, то забудь слово «эффективность».

Идеи для собственного велосипеда имеются, но зачем его изобретать, если вдруг он уже есть?

Опять эти куллстори - если бы у тебя были «идеи» и ты мог бы это написать - ты бы не спрашивал такую херню.

С таким успехом, с которым это решает типичное днище - это решается тупым и примитивным шедулером сверху.

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

А с чего ты решил, что для домохозяек есть что-то лучше?

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

Да с чего вы все взяли, что mmap что-то принципиально ускоряет??? mmap устраняет лишнее копирование памяти, которое, вообще говоря, не обязательно имеется и при обычном вводе-выводе. Тема же про другое.

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

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

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

Напиши тест. Скорее всего - всё нужное тебе можно настроить через планировщик. Под оффтопиком оно кстати тоже более менее настраиваемо, говорят.

Если хочешь быстрой кроссплатформы, то std:: это всё равно не то, что тебе нужно. Оно заточенно под портабельность.

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

Кстати, когда я говорил про кэш - я имел ввиду, имено кэш в памяти.

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

pon4ik ★★★★★
()

В принципе, выше уже ответили, но все же, чтобы ты не питал особых иллюзий...

кросплатформенное решение для c++, которое бы организовывало эффективное кэширование и сериализацию чтения

Такого не может существовать в принципе, потому что на каждой ОС свои механизмы для дискового IO. Также в принципе не может существовать алгоритма, способного предсказать, какой сегмент файла запросит пользовательское приложение в следующий момент времени, поэтому изобрели костыль под названием AIO, который по факту позволяет задавать «пачки действий» без ручного создания потоков, занимающихся IO.

Если ты попытаешься умничать и, скажем, отключишь readahead и займешься аккумуляцией и сортировкой оффсетов для чтения (читай: изобразишь свой IO scheduler в userspace), то ничего путного снова не выйдет, т. к. ты не обладаешь никакой информацией о физическом расположении частей файла. Это знает только ОС.

TLDR: в треде уже сказали: не выпендривайся и жри, что дают. Если хочешь эффективности, отказывайся от кроссплатформенных оберток (использовать плюсовые стримы и требовать «производительности» — верх идиотизма). В Linux AIO избегай, потому что оно не дружит с pagecache. В онтопике лучше пула потоков, делающих sendfile, пока еще ничего не изобрели.

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

Такого не может существовать в принципе, потому что на каждой ОС свои механизмы для дискового IO. Также в принципе не может существовать алгоритма, способного предсказать, какой сегмент файла запросит пользовательское приложение в следующий момент времени

О мой кот. Откуда столько царей и учителей? Я же тебе русским языком написал какой сегмент будет прочитан в следующий момент времени. Если ты не понял, то тебе нечего делать в этой теме. Бери с собой царя и идите отдыхайте.

asaw ★★★★★
() автор топика

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

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

Когда вычитывают несколько файлов (которые физически находятся в разных областях диска), все может упираться в позиционирование головок https://en.wikipedia.org/wiki/Hard_disk_drive_performance_characteristics

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

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

Он всегда занимал близкую к си позицию в иерархии языков. Между жавой и плюсами - плюсы, между си и плюсами - си.

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

nginx использует именно его.

Вот прямо на винде его и использует?

Потом, у меня вопрос про чтение в юзерспейс. Потому что не всё на свете исчерпывается TCP, есть ещё UDP.

asaw ★★★★★
() автор топика

Подключи сервак к флешевому SAN'у через 16-гбит FC.

mv ★★★★★
()

то узким местом становится дисковая подсистема

вот именно, и в итого, либо много труда вкладывается в оптимизацию кода кросплатформенного «http- и ftp-сервера» с учётом особенностей задачи и всевозможных систем. Любо выбирают и настраивают ФС с учётом железа и задач. Как, например, Lustre, где кэш ФС занимает 90% ОЗУ на объектных серверах.

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

Вопрос не такой общий и не такой сложный. Всего-то требуется передать один флажок в кроссплатформенном виде. Либо организовать довольно простую буферизацию (во втором приближении).

asaw ★★★★★
() автор топика

ТС, ты либо читай эффективно последовательно, либо неэффективно параллельно. Никакие nmap-ы и прочее тебя не спасут. Зачем винты по твоему дефрагментируют? Затем чтобы данные файлов лежали последовательно, т.к. считывающая головка на винте последовательно быстрее работает. Сервера зачастую свой кеш имеют, куда запихивают наиболее часто скачиваемые файлы. А с нагруженной на запросы БД вообще рекомендовано иметь оперативки столько же, сколько весит твоя БД, чтобы её с диска не читать кроме как при включении серванта. Потому на многих серверах в продакшене стоит 192гб+ оперативки.

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

Кэп, я это всё понимаю. Я не понимаю почему в стандартных fstreams нет возможности передать один единственный флажок, который указывал бы ОС, что чтение из файла, связанного с потоком, будет происходить преимущественно последовательно (сюрприз!), либо произвольно. И у меня нет желания лишний раз писать свой велосипед, который преобразовывал бы паттерн чтения данных из того, который удобен в моей программе, в тот, который удобен НЖМД. Такие вещи уже должны быть давно написаны.

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

Э, потому что это есть не во всех ОС, где есть поддержка C++. C++ не должен решать эту проблему. Эту проблему должно решать что-то ОС специфическое. А вот почему ты не нашел кроссплатформенную обёртку для этого или не сделал её сам - вопрос.

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

Кстати, профилировщик что говорит по твоей проблеме?

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

нет, тк эти данные можно получить через ioctl, они доступны дальше, чем в фс

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

Итак, что мы узнали о царе в новых сериях? Царем движет страх перед «талмудами» - читает он, видимо, так же, как и пишет - но при этом у него есть опыт обучения по системе «дебил-дебилу», вынесенный из сообществ доты и генты, и царь, возможно несознательно, подыскивает себе такой формат на лоре.

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

Э, потому что это есть не во всех ОС, где есть поддержка C++.

Флажка нет потому что он поддерживается не всеми ОС? А чем помешает его наличие если он не поддерживается? Подумай прежде чем печатать.

C++ не должен решать эту проблему. Эту проблему должно решать что-то ОС специфическое. А вот почему ты не нашел кроссплатформенную обёртку для этого или не сделал её сам - вопрос.

Я уже раз 10 об этом написал в этой теме. Надоело.

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

а не ФС?

ФС лежит поверх block device, роль которого может исполнять в том числе и LVM.

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

Флажка нет потому что он поддерживается не всеми ОС? А чем помешает его наличие если он не поддерживается?

Тем что библиотека шаблонов будет содержать всякую хрень, которая поддерживается далеко не везде, разве не так?

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