Пишу копирование (фрагментов) файлов в винде, как лучше?
попробуй наращивать размер блока, пока не достигнешь максимума =)
>каким АПИ лучше пользоваться?
native api
С размером конечно можно поэкспериментировать, но боюсь там все зависит от многих факторов. Хотелось бы какое-никакое общее представление иметь, исходя из которого можно оценивать какой вариант лучше.
А вообще вопросов возникает довольно много: например, создавать сразу файл необходимого размера или нет, писать через файл-меппинг или как-то еще и т.д.
А чем время-то не устраивает?
Хотелось бы какое-никакое общее представление иметь, исходя из которого можно оценивать какой вариант лучше.
Имхо, большой выигрыш так не получить.
создавать сразу файл необходимого размера или нет, писать через файл-меппинг или как-то еще и т.д.
про native api я пошутил
основной вопрос в размере блока чтения файла. Эта величина находится экспериментально
а как ты пишешь в джава: через ридеры/райтеры?
По моим экспериментам, оптимальный размер блока - от полумегабайта до 4-6мб, но я думаю, что эти величины могут сильно колебаться в зависимости от lan и компьютеров
Правильно я понимаю, что если проделать эксперимент, когда я в цикле пишу файл, например, размером в 200мб, блоками фиксированного размера, то получается, что оптимальным будет размер блока 4-6мб, т.е. весь файл запишется максимально быстро.
Такой большой? Можешь пояснить какую роль этот блок играет, т.е. как ты с ним работаешь, с лана читаешь 4мб, а потом их пишешь на диск?Да, сначала читаю блок, потом пишу на диск, потом снова читаю и т. д.
Я писал, что оптимальный размер блока от полумегабайта до 4-6мб. Это лишь результат моих немногочисленных экспериментов по оценке скорости копирования.
Правильно я понимаю, что если проделать эксперимент, когда я в цикле пишу файл, например, размером в 200мб, блоками фиксированного размера, то получается, что оптимальным будет размер блока 4-6мб, т.е. весь файл запишется максимально быстро.
Думаю, вот что может служить обоснованием полученных величин:
* Скорость копирования падает при увеличении частоты запросов на чтение очередного блока (т. е. , например, нельзя копировать блоками по 10 байт). Связано в основном с издержками сети
* Скорость падает при увеличении размера буфера. (например, нельзя читать фильм кусками по 100мб). Это связано с тормознутостью виртуальной памяти компьютера.
* Экстремум находится где-то посередине .
Если копировать нужно множество файлов одновременно с из нескольких источников на один приемник, то узким местом становится количество памяти на приемнике, т. к. под каждый поток по-хорошему нужно выделить память на блок чтения. Эту проблему можно решать разными способами...
О, большое спасибо. А то искал в МСДН, заглянул в Девайс ИО, а в Фаил Сервисес не заметил.
Первое, что не нравится в твоей схеме, это то, что ты читаешь и пишешь по очереди. Если я конечно правильно понял, что ты не делаешь это одновременно.
Мне всегда казалось, что в винде ИО осуществяется как последовательность элементарных запросов на ИО, поступающте запросы буферизируются в очереди, и как-то пачками обрабатываются. При этом на этом уровне не так важно, как эти запросы формировались: либо мало райтов большого размера, либо больше райтов меньшего размера. Это конечно если делать райты правильно, через какие-нибудь асинхронные АПИ. Просто когда ты делаешь синхроные райты, то конечно их реализация "хорошая" -- формируется очередь запросов на ИО, которые будут выполняются. При этом следующий синхронный райт у тебя пойдет, только после того как закончится предыдущий, т.е. когда выполнятся все его запросы на ИО. Т.о. у тебя не получается непрерывный поток запросов на ИО. В принципе, если ты пишешь большими блоками, то этот негативный эффект незначителен.
Т.о. если такое представление о ИО в винде верно, то пользуясь правильными АПИ можно иметь ту же скорость при гораздо меньших размерах блока чтения/записи. Тогда правильная реализация читает и пишет параллельно, и при этом она не нуждается в большом буфере. Большой буфер тебе нужен только для того, чтобы склаживать подтормаживания источника и назначения: если упадет скорость записи, но будет набиваться буфер на полной скорости чтения, если упадет скорость чтения, то можно на полной скорости пистать содержимое буфера.
Ладно, осталость проверить, на сколько все это соответсвует действительности.
Просто, если делать, то интересно делать это правильно
Если я пользуюсь "обычным" api, то у меня синхронизированная запись. Но у NT есть буферезированная запись. Буферезированная запись для операций a1...an работает быстрее, чем синхронизированная для этих же кусочков. Если NT разделяет буферезированные запросы по транзакциям примерно одинаковой сложности, то использование достаточно большого буфера чтения и синхронизированного api записи не снижает скорость в сравнении с буферезированным api. Так?
Я проблему памяти на приемнике решил ограничением сверху используемой памяти: буферы чтения находятся в пуле, из которого извлекаются по необходимости и сразу возвращаются назад. Количество блоков памяти в пуле ограничено
На мой взгляд, смысл буферезированных операций есть при копировании большого числа файлов маленького размера. Но, к сожалению, я ни разу не видел действительно быстрой реализации такого копирования.
Другой вариант использования буферезированного API - очень много источников в сети, каждый из которых очень медленный, но в совокупности они дают большой траффик. В случае jdownloader - это редкая ситуация
Несколько раз перечитал твой пост, понял вот что:Типа того, с учетом того, что я см плаваю в терминологии, и до конца сам не понимаю что говорю.
Если я пользуюсь "обычным" api, то у меня синхронизированная запись. Но у NT есть буферезированная запись. Буферезированная запись для операций a1...an работает быстрее, чем синхронизированная для этих же кусочков. Если NT разделяет буферезированные запросы по транзакциям примерно одинаковой сложности, то использование достаточно большого буфера чтения и синхронизированного api записи не снижает скорость в сравнении с буферезированным api. Так?
писать через файл-меппинг или как-то еще и т.дОчень не рекомендую использовать мэппинг. Там с большими файлами проблемы часто бывают (которые в память не влазят сам сталкивался.
или это у шарпа какие-то личные проблемы с этим?
там с мепингом проблема, что скорее всего кеш забивать будет
причем здесь шарп?
Я когда-то использовал мэппинг для графического отображения wav'ов. Пока они были небольшими, все работало. Стоило же перейти на файлы, сравнимые по размеру с объемом оперативки, как пошли ошибки, не удавалось с ними также работать. Подробности сейчас не помню, ибо было это давно. Писалось на VC6 под XP.
заюзать gnuutils и написать шеллскрипт?
под винду?
http://unxutils.sourceforge.net/
мож это чем поможет...
мож это чем поможет...
Оставить комментарий
bastii
Задача копировать много файлов из нескольких мест, в несколько мест. Но пока интересует как это делать с одним файлом, одним источником и одним местом назначения. Файлы копируются с винтов на винты, хотелось бы это делать с максимальной скоростью.В принципе интересует общая идея, как это делать в винде (т.е. дотнет не обязательно).
Можно, например, считать блок, записать блок и т.д. При этом наверно лучше читать и писать параллельно. Вопрос как все таки лучше это делать, и как лучше запрограммировать. Как лучше организовать потоки и буферы? Может кто экспериментировал с вводом/выводом в винде, какой размер блока для записи/чтения оптимален, каким АПИ лучше пользоваться?