Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Оптимизация распаковки множества мелких файлов на диск

78K
15 августа 2013 года
albeoris
20 / / 17.05.2013
Всем привет!

Суть проблемы
Есть архив, содержащий другие архивы, которые содержат другие архивы, которые... в сумме дают 18726 файлов общим весом 1 447 147 737 байт.
Архивы распаковываются в 4 потока. Узким местом является диск. Модификация аппаратной части не рассматривается.
Распаковка занимает порядка 5 минут. Хочется уменьшить раз эдак в 5.

Вопрос: существуют ли стандартные средста, позволяющие буферизовать сбрасываемые на диск изменения точно также, как буферизуется запись отдельных файлов.
Тоесть хочется выделить в памяти большой буфер, например 200 мб, разметить, как виртуальную файловую систему, создавать в ней каталоги, файлы. А когда буфер заполнится - сбросить его на диск, единым махом влив большой объем данных в однопоточном режиме.

Если стандартных средств нет, быть может, кто-нибудь подскажет - в какую сторону стоит копать?

Прежде чем предлагать написать драйвер для мапящейся в память ФС, задумайтесь о том, что основная проблема не в том - куда писать, а как потом эту виртуальную ФС объединить с реальной, за 1-10 действий, а не за 18726 * X. ;)
78K
15 августа 2013 года
EsEr
20 / / 17.02.2013
Создать виртуальный ЖД и распаковывать в него, а потом в хоть в 1000 потоков копировать файлы на реальный ЖД. :)
78K
15 августа 2013 года
albeoris
20 / / 17.05.2013
Создать виртуальный диск в памяти, распаковать в него, сбросить виртуальный диск на жесткий - идея отличная. На на выходе мы получим всё тот же виртуальный диск, а нужна рассыпуха файлов. Опять же, буфер в 200 мб - это одно. А виртуальный диск в 1Гб в памяти - это очень неповоротливая махина. Ну, а если копировать после этого файлы в виртуального диска на жесткий, вернемся к начальной ситуации.
10
15 августа 2013 года
Freeman
3.2K / / 06.03.2004
Как минимум, хотя не уверен, что сильно поможет:

 
Код:
REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"NtfsDisable8dot3NameCreation"=dword:1
"NtfsDisableLastAccessUpdate"=dword:1
7
15 августа 2013 года
@pixo $oft
3.4K / / 20.09.2006
Создать в памяти буфер в несколько сотен Мб (в котором по какому-то правилу будут храниться извлечённые файлы — считай, виртуальная ФС), при заполнении сбрасывать его на диск. Причём можно сделать его либо кольцевым (но тогда придётся контролировать, что перезаписываемый блок уже сбросился на диск), либо делать 2 буфера — пока сбрасывается 1-й. пишем во 2-й, и наоборот.
78K
16 августа 2013 года
albeoris
20 / / 17.05.2013
Цитата: @pixo $oft
Создать в памяти буфер в несколько сотен Мб (в котором по какому-то правилу будут храниться извлечённые файлы — считай, виртуальная ФС), при заполнении сбрасывать его на диск. Причём можно сделать его либо кольцевым (но тогда придётся контролировать, что перезаписываемый блок уже сбросился на диск), либо делать 2 буфера — пока сбрасывается 1-й. пишем во 2-й, и наоборот.


Да разумеется, вот только на диске мне нужен не бинарник размером в 1.5 Гб, а набор этих самых файликов.

Вот, к примеру, тебе нужно распаковать zip-архив, в котором лежат 80 000 файлов по 200-10000 байт каждый. Ты распаковываешь его в память, получаешь буфер в 380 мб. Сбрасываешь на диск. И... что дальше? Нет, конечно можно написать просмоторщик, который будет работать с таким файлом. И что-то мне подсказывает, что я так и поступлю. Но всё-таки хотелось бы перед этим увериться в том, что не существует волшебного способа превратить этот здоровый бинарник в кучку файликов, смапив на него имена файлов, их длины и смещения.

326
16 августа 2013 года
sadovoya
757 / / 19.11.2005
В озу формировать iso-образы и сбрасывать на хард. Работать с ними с виртуального cd-привода -- как такой вариант? А в линухе можно было бы файловую систему внутри файла мелкоблочную сделать..

Да и вообще, такие мелкие файлы в виндовых файловый системах -- вечные тормаза и фрагментация. Лучше хотя-бы тот-же просмотрщик по-любому сделать.
260
16 августа 2013 года
Ramon
1.1K / / 16.08.2003
Вы не поверите, системный кэш все это уже делает, главное ему не мешать, а иногда подсказывать, ну и не съедать физ. память. А что до конкретного случая, что за архив, чем распаковывается, какой профиль у приложения и тд и тп. Ну и самый занятный следующий из всего этого вопрос - утверждение: "узким местом является диск", основано на чем?
78K
16 августа 2013 года
EsEr
20 / / 17.02.2013
Цитата: albeoris
Создать виртуальный диск в памяти, распаковать в него, сбросить виртуальный диск на жесткий - идея отличная. На на выходе мы получим всё тот же виртуальный диск, а нужна рассыпуха файлов. Опять же, буфер в 200 мб - это одно. А виртуальный диск в 1Гб в памяти - это очень неповоротливая махина. Ну, а если копировать после этого файлы в виртуального диска на жесткий, вернемся к начальной ситуации.


Немножко не поняли мой ответ. Виртуальный ЖД в памяти будет выполнять роль реального, раз реальный является "узким местом", распаковка и запись в такой виртуальный диск будет происходить в 10ки раз быстрее, копирование с него на реальный жесткий можно организовать в несколько потоков, выделением областей реального жесткого для каждого(или нескольких) файла и последующей записью в выделенные области на реальный ЖД. Вот как то так. Насколько это реализуемо программно, я не знаю, исхожу только из своих знаний о работе ЖД.

78K
16 августа 2013 года
albeoris
20 / / 17.05.2013
EsEr
Как уже писалось, проблема как раз в том, чтобы перенести после этого содержимое виртуального диска на реальный. Нужно всю ту виртуальную громадину превратить в кучу мелких файликов на диске.

sadovoya
Я уже озвучивал идею с виртуальным монстром. Проблема в том, что он, по понятным причинам, будет read-only. А значит при необходимости что-либо изменить, придётся либо создавать новый "диск", с разницей, либо просто скидывать рядом уже отдельные, измененные файлики. В принципе, последний вариант устраивает. Но... не идеален.

Цитата: Ramon
Вы не поверите, системный кэш все это уже делает, главное ему не мешать, а иногда подсказывать, ну и не съедать физ. память. А что до конкретного случая, что за архив, чем распаковывается, какой профиль у приложения и тд и тп. Ну и самый занятный следующий из всего этого вопрос - утверждение: "узким местом является диск", основано на чем?


Не поверю! :D
А можно узнать - как он это делает? Потому что я ему явно мешаю. Архив совершенно кастомный. Описан вверху. Дополню описание распаковки:
Есть очередь, которую теребят 4 потока. В неё помещается исходный архив. При распаковке, вложенные архивы также добавляются в эту очередь. Обработка происходит, пока очередь не опустеет.
Кстати, возможно, ты прав - потому что повторная распаковка пролетает раз в 10 быстрее. Вероятно, какие-то механизмы для оптимизации существуют. Правда, как-то уж очень сомнительно, что тут помогает кэш. Потому что я просто дёргаю за стандартные механизмы создания файлов, передавая им абсолютные пути и начинаю поточную запись. Закрываю, перехожу к следующему файлу. И так, пока архив не опустеет.
Насчёт узкого места - потому что 90% времени программа ожидает окончания сброса данных на диск.

260
16 августа 2013 года
Ramon
1.1K / / 16.08.2003
Цитата: albeoris
Насчёт узкого места - потому что 90% времени программа ожидает окончания сброса данных на диск.


Барьер ввода/вывода или тупо ф-ции read/write?
Без профиля и топа 10, могу сказать лишь банальность - используйте отображенные в память файлы как минимум для чтения архивов, а лучше и для записи, так вы хотябы сэкономите многократные никому не нужные копирования памяти на которых и сидите в read/write'ах, по большей части.
А все остальное зависит от структуры самого архива.

PS: Лекции по внутреннему устройству всяких подсистем предпочитаю не читать.

78K
16 августа 2013 года
albeoris
20 / / 17.05.2013
Цитата: Ramon

Барьер ввода/вывода или тупо ф-ции read/write?
Без профиля и топа 10, могу сказать лишь банальность - используйте отображенные в память файлы как минимум для чтения архивов, а лучше и для записи, так вы хотябы сэкономите многократные никому не нужные копирования памяти на которых и сидите в read/write'ах, по большей части.
А все остальное зависит от структуры самого архива.

PS: Лекции по внутреннему устройству всяких подсистем предпочитаю не читать.


Ввода-вывода. Read\Write пролетает моментально.
А в чём профит отражения? Забивать кэш, читая по 4кб вместо физ.памяти по 32кб (у меня такой размер буфера). Я перепишу - мне не сложно, но хотелось бы знать, что это не просто бессмысленные манипуляции, а нечто жизненноважное, что даст существенный (хотя бы в 20%) прирост производительности.

P.S. А вот про лекции ты зря. Я как раз подумываю о том, чтобы открыть диск и писать напрямую в него, самостоятельно делая записи в MFT (поддержка только NTFS). Правда, не представляю ещё как это делается. В моём понимании, нужно отсортировать все данные (в памяти) на крупные и мелкие, крупные слить в единый блок, мелкие склеить с MFT-заголовками, после чего выставить в журнале транзакций 20 000 флагов, скинуть на диск два буфера - один в MFT, другой по месту дислокации крупных файлов, снять 20 000 флагов. (Извращенный вариант).
Более человеческий - писать всё в один файл на диске, попутно формируя MFT-заголовки, после чего склеить их, опять же поднять флажки транзакций, влить данные, флажки снять. Если флажок 1, а не 20 000 - круто. Но всё ещё плохо себе представляю, как работать с MFT в среде, где ни я один создаю\ударяю файлы, запущены дефрагментаторы и прочие прелести.

414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
Раз такой топик существует, спрошу тут.
Читал, что обладатели SSD винтов переносят TMP каталог в память, чтоб лишний раз не писать на физический винт. Они это как-то делают средствами системы. Может, кто-нибудь расскажет, что для этого настраивается и как оно работает? Обладатели SSD винтов присутствуют?
78K
16 августа 2013 года
albeoris
20 / / 17.05.2013
Цитата: CassandraDied
Раз такой топик существует, спрошу тут.
Читал, что обладатели SSD винтов переносят TMP каталог в память, чтоб лишний раз не писать на физический винт. Они это как-то делают средствами системы. Может, кто-нибудь расскажет, что для этого настраивается и как оно работает? Обладатели SSD винтов присутствуют?


Как-то совсем не по адресу, но ладно уж:
ПКМ по "Мой компьютер" - Свойства - Дополнительно - Переменные среды - Ищешь TMP и TEMP, задаешь новый путь. Убедись, что каталог, который ты указываешь существует.
Только смысл? SSD служит для увеличения скорости работы системы. Перенес временные файлы - операции с ними будут выполняться медленнее. Притом, что пишут в них обычно как раз системные программы. С тем же успехом, можно вообще перенести с него всё, включая систему, забить фильмами, вытащить из компа, наклеить табличку "неприкосновенный запас" и никогда не использовать.
Купил SSD - пользуй его по полной. Нескольких сотен тысяч циклов перезаписи тебе хватит до того момента, как он сдохнет по другой причине или просто морально устареет.
Главное: не забивай под завязку. Если у тебя на нём останется 500мб свободного места, то ты его действительно быстро угробишь. Держи хотя бы 30% пространства свободным. Настрой дефрагментацию на более редкие запуски (н.п. раз в 2 месяца) и будет тебе счастье.

414
16 августа 2013 года
CassandraDied
763 / / 24.05.2012
И каким образом мне задать новый путь в оперативной памяти?
326
16 августа 2013 года
sadovoya
757 / / 19.11.2005
Слышал, чтобы износ снизить, оключают файл подкачки. Думаю не лишнее - откючить еще префетч. Стоит ли его вообще дефрагментировать?
В линуксе следует избегать журналируемых файловых систем, в виндовс -- особого выбора нет.
Цитата:
И каким образом мне задать новый путь в оперативной памяти?


Вероятно создать виртуальный диск в озу и уже туда. У них какая Винда, 7-ка вроде позволяет своими средствами диск в памяти создавать.

78K
17 августа 2013 года
albeoris
20 / / 17.05.2013
Цитата: CassandraDied
И каким образом мне задать новый путь в оперативной памяти?


Извини, не заметил про память. Тебе сюда:
http://ru.wikipedia.org/wiki/RAM_drive#Windows
Стандартными - не знаю, не пробовал.

А путь задаёшь, как обычно - подмаунтил диск, назначил букву тома.

414
17 августа 2013 года
CassandraDied
763 / / 24.05.2012
albeoris, спасибо за информацию. Жаль. Думал, что можно стандартными средствами.
10
17 августа 2013 года
Freeman
3.2K / / 06.03.2004
Ха-ха-ха, а не может быть так, что все дело в установке размера файла перед записью? Насколько помню, запись в файл, отображенный на память, возможна только в том случае, когда размер его известен, поэтому его приходится устанавливать перед вызовом функции отображения. Опыты проводить лень.
7
17 августа 2013 года
@pixo $oft
3.4K / / 20.09.2006
От нечего делать решил почитать. Возможно, ты попутал с этим:
Цитата:
If hFile is INVALID_HANDLE_VALUE, the calling process must also specify a size for the file mapping object in the dwMaximumSizeHigh and dwMaximumSizeLow parameters.

Хотя читаю дальше и вижу, что надо задавать максимальный размер файла, так что да, не всё так чисто.

92K
10 декабря 2013 года
AlCoi
1 / / 10.12.2013
Теоретическая реализация.
создаем 2 файла: Первый непосредственно на диске под содержимое файлов, Второй под информацию о этом содержимом в нем будет хранится инфа в виде ИМЯФАЙЛА/размер/ (его можно и даже НУЖНО для ускорения операции создать в памяти в виде массива). Создаем файл 1 размером сразу примерно равным распакованномым данным (а лучше загрести сразу больше чем надо!) заполняя его содержимым распакованных файлов периодически увеличивая размер если зарезервировали недостаточно. Пичем писать нужно инфу таким образом, чтобы у нас неполучилась в последствии ситуация когда начало следующего файла в последнем кластере предыдущего (нехитрой формулой вычисляем количество байт для заполнения последнего кластера файла). Для быстроты конечно нужно писать здоровыми блоками из буфера где содержимое нескольких распакованных файлов расположено последовательно правильным образом. При этом заполняем второй файл соответствующей информацией о записаном содержимом файлов записями вида ИМЯФАЙЛА/размер/. В конце операции распаковки имеем на винте здоровый файл с содержимым распакованных файлов и файл (или массив в памяти) с разметкой этого содержимого. Этот этап довольно прост в реализации, далее будет посложнее.
Теперь нам на основании карты кластеров первого файла (читаем ее из файловой системы) и информации из второго необходимо сформировать команды на принудительное создание в МФТ множества записей соответствующих расположению данных распакованных файлов в нашем гигантском файле.
И только после этого пометить первый файл как удаленный и вуаля, имеем кучу файлов из одного гигантского.
Для практической реализации нужно создать собственно структуру каталогов на диске, прикрутить во второй файл инфу о соответствии файлов каталогам и применять ее на последнем этапе.
Впринципе кэширование записи должно примерно так и работать, резервирует место/скидывает дату нескольких файлов/формирует записи в фс, но буфер там невелик.
В моем же методе скидываем сперва ВСЕ ДАННЫЕ, только затем создавая записи мфт тем самым уменьшая накладные расходы на беготню головок и кучу операций чтения/записи резервирования данных на диске.
78K
12 декабря 2013 года
albeoris
20 / / 17.05.2013
Примерно так и предполагал. А можно чуть подробнее о второй части? Как? Чем? Что почитать? Где подсмотреть?
Ведь структура каталогов бэкапится и хранится в нескольких экземплярах на HDD. Тоесть есть какие-то стандартные средства для её изменения? Было бы шикарно увидеть пример полностью низкоуровневого создания каталога с несколькими файлами на чём-нибудь повыше ассёмблера. А то мне сейчас представляется проще написать драйвер для маунта такого бинарника на файловую систему, чем то, что описал ты. :D
326
14 декабря 2013 года
sadovoya
757 / / 19.11.2005
Ассемблер тут вряд ли и поможет. Все одно через Win Api работать. Копайте в сторону системных ф-ций для работы с MFT. Но, что то мне подсказывает, что доступ к MFT проблемен до жути -- недаром дефрагментаторы могут ее обработать только при перезагрузке.

P.S. А возможности CreateFile() / WriteFile() / ReadFile() и настроек реестра все исчерпаны? Там столько параметров для настройки, что "крыша едет", мне в полной мере освоить инфу MSDN по ним до сих пор не удалось. Ясно одно -- там есть шанс поднять эффективность.
78K
16 декабря 2013 года
albeoris
20 / / 17.05.2013
Да, поднять можно, но на локальной машине. Не на клиентской "из коробки". То же не обновление даты изменения файлов.
А так очень хотелось бы лёгким движением хвоста превратить один файл в 20 000. :)
326
16 декабря 2013 года
sadovoya
757 / / 19.11.2005
Может утилиту dd задействовать. Это юниксовая вещь для блочного сырого копирования, но в MinGW есть порт виндовый. Пишим в один файл, потом его стираем. Дальше, а фиг знает.. Еще фиг знает, можно ли ею из памяти писать. В общем, может вас на какую идею наведет.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог