LINUX.ORG.RU

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

 


1

3

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

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

Кончай уже писать хрень. Посмотри на TS filesystem: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4099.html#enum.perms То, что большинства из этих флажков нет в Windows никак не мешает стандартизации.

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

Ещё раз это не дело C++ и один флаг не решает проблемы. То о что вам надо - это параметры ФС, которые могут быть совсем не тривиальными. Посмотри на стандартный тест производительности Ext4: http://www.bullopensource.org/ext4/20080818-ffsb/ffsb-readwrite-2.6.27-rc1.html

Не забывайте, что кроме вашей программы, которая считывает «случайным» образом части большого файла или открывает большое количество файлов, есть и другое ПО.

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

И ты тоже можешь отдыхать, раз не понял вопроса.

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

И не говори. Уже SSD скоро всё вытеснят, а такой простой вещи для HDD так и нет...

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

чтение из файла, связанного с потоком, будет происходить преимущественно последовательно (сюрприз!), либо произвольно

потоком

произвольно

ок.

Подумай прежде чем печатать.

таким образом, всего-то надо найти (или навелосипедить) подходящую тебе реализацию std::fstream

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

Попробовал boost::iostreams::file_descriptor вместе с http://www.boost.org/doc/libs/1_58_0/libs/iostreams/doc/guide/generic_streams... Жуть. Чтобы заставить этот хлам на макросах хотя-бы просто компилироваться, нужно писать код вроде вот такого:

    bool success = false;
    int fd;

#ifdef _WIN32
    _wsopen_s(&fd, path.c_str(), _O_RDONLY | _O_BINARY | _O_SEQUENTIAL, _SH_DENYWR, _S_IREAD | _S_IWRITE);
#else
    fd = open(path.c_str(), O_RDONLY);
#endif

    if (fd != -1) {
        ifs.open(static_cast<const int&>(fd), static_cast<const boost::iostreams::file_descriptor_flags&>(boost::iostreams::close_handle));
        success = ifs.good();
    }
Обращаю внимание на касты. Если проинициализировать поток дескриптором при создании, а потом пытаться делать ему его же (не дескриптора) open() после соответствующего close(), то вылетает segmentation fault. Но это ещё полбеды. Беда приходит с открытием большого числа потоков. Эта хрень просто перестает ворочаться. В общем, в моем списке это одна их худших библиотек boost, которая, наверное, обгоняет даже boost.log v2 по отстойности. И при всех этих убогостях и тормознутости она тоже не header-only. Так что по сравнению с ней даже самодельный велосипед будет лучшим решением.

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

У DMA минимальный размер блока 1k

Сектор != блок, не?

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

А какая альтернатива?

Должен заметить, что в моем случае я столкнулся с проблемами в основном под виндой. Решение было такое:

    FILE* stream = _wfsopen(path.c_str(), L"rbS", _SH_DENYWR);
    if (stream != nullptr) {
        std::ifstream newIfs(stream);
        if (newIfs.good()) {
            success = true;
            ifs.swap(newIfs);
        }
        else
            fclose(stream);
    }

То есть это stdio вместе с iostreams. И вот это вот позволило поднять производительность минимум в 30 раз - далее уже сеть стала узким местом. Сами по себе iostreams тормозом не являются.

P.S. В данном конкретном примере у использования stdio и iostreams есть другой минус - в оффтопике есть жесткий лимит на число одновременно открытых файловых дескрипторов из stdio и он смехотворно низок - всего 2048 (по умолчанию и вовсе 512). Причем, нужно помнить, что сокеты используют те же дескрипторы. То есть решение всё равно получается ограниченным даже если бы в iostreams был бы нужный флажок. А в Win32 API такого ограничения нет. Правильное кроссплатформенное решение должно учитывать и такие особенности.

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

Обычно быстрее сделать свой велосипед, чем разбираться в чужом, да ещё таком большом. Нужна готовая к использованию библиотека.

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

Это зависит от результата который ты хочешь получить. Вайн в нужном тебе месте довольно хорошо вылизан и отлажен. Ну как минимум в разы лучше за stdio и iostreams

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