Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель.
Пишу так (на С)
while (!feof(источник)) {
fread(buffer, источник);
fwrite(buffer, приемник);
}
источник — файл на диске, приемник файл на флешке.
Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее)
Размер буфера результатов на дал.
Почему?
Здравствуйте, Su34, Вы писали:
S>Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель. S>Пишу так (на С) S>while (!feof(источник)) { S> fread(buffer, источник); S> fwrite(buffer, приемник); S>} S>источник — файл на диске, приемник файл на флешке. S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее) S>Размер буфера результатов на дал. S>Почему?
Размер кратен 2^n ?
Здравствуйте, Su34, Вы писали:
S>Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель. S>Пишу так (на С) S>while (!feof(источник)) { S> fread(buffer, источник); S> fwrite(buffer, приемник); S>} S>источник — файл на диске, приемник файл на флешке. S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее) S>Размер буфера результатов на дал. S>Почему?
Здравствуйте, kov_serg, Вы писали: _>Размер кратен 2^n ?
256,512,1024,2048,...1024*1024 без разницы!
Буфер равен сектору — нет эффекта. В данной конструкции вообще нет никаких камней!
fopen(source, "rb");
fopen(dest, "wb");
while (!feof(source))
fread(buffer, source);
fwrite(buffer, dest);
fclose(source); fclose(dest);
Здравствуйте, Su34, Вы писали:
S>Здравствуйте, kov_serg, Вы писали: _>>Размер кратен 2^n ? S>256,512,1024,2048,...1024*1024 без разницы! S>Буфер равен сектору — нет эффекта. В данной конструкции вообще нет никаких камней! S>fopen(source, "rb"); S>fopen(dest, "wb"); S>while (!feof(source)) S> fread(buffer, source); S> fwrite(buffer, dest); S>fclose(source); fclose(dest);
Проблема точно в этом методе?
А покажите полный код метода.
Здравствуйте, Su34, Вы писали:
S>Здравствуйте, kov_serg, Вы писали: _>>Размер кратен 2^n ? S>256,512,1024,2048,...1024*1024 без разницы! S>Буфер равен сектору — нет эффекта. В данной конструкции вообще нет никаких камней! S>fopen(source, "rb"); S>fopen(dest, "wb"); S>while (!feof(source)) S> fread(buffer, source); S> fwrite(buffer, dest); S>fclose(source); fclose(dest);
Для эксперимента уберите fread и замените буфер просто случайными значениями.
Здравствуйте, BlackEric, Вы писали: BE>Есть готовые функции в винде для копирования: CopyFileExA function (winbase.h) BE>Тотал скорее всего через них работает
Уходим за рамки раздела "Железо", но все же!
Если разделить процесс копирования файла на 2 потока, поток чтения и поток записи можно увеличить скорость копирования файла (для одного диска это эффекта не даст, будет даже обратный, а вот для разных устройств эффект есть). Я не думаю что CopyFileEx так сложно устроена!
Поэтому своя функция копирования.
Здравствуйте, Su34, Вы писали:
S>Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель. S>Пишу так (на С) S>while (!feof(источник)) { S> fread(buffer, источник); S> fwrite(buffer, приемник); S>} S>источник — файл на диске, приемник файл на флешке. S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее) S>Размер буфера результатов на дал. S>Почему?
У total была "фишка" что он фактическую операцию копирования файла выполнял через кэш в фоне. для пользователя это так и выглядело в 5 раз быстрее. но лампочка активности usb HDD еще долго мигала после "окончания".
S>приемник файл на флешке.
USB-шной? ))
Ваша fwrite она блокирующая функция?
Ждёт завершения вероятно?
А у USB есть frame. Пока он не пройдёт подтверждение не получите
А что такие буферы маленькие?
Вы наверно издеваетесь
Вообще странный тест
Если проблема со скоростью записи
Не надо читать
Пишите в неё рандомный буфер
Замеряйте время
Сделайте тесты для разных размеров
Только не идиотксие 512 байт
Ну хотя бы 0x10000, 0x100000 байт
Сравните с виндовым FileWrite
Попробуйте файл целиком загрузить в память
И целиком записать. Ну 100МБ, например
Здравствуйте, BlackEric, Вы писали: BE>Почему там 1?
int result = fread(buf, 1, block_size, src); вернет фактическое значение прочитанных байт
int result = fread(buf, sizeof(buf), block_size, src); вернет 0 или 1
Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb!
Меня это конечно удовлетворяет, но...
1. Как быть с кросплатформой.
2. Что же спрятано в WriteFile.
Кстати, std::filesystem::copy_file грешит тем же самым!
Здравствуйте, Su34, Вы писали:
S>Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb! S>Меня это конечно удовлетворяет, но... S>1. Как быть с кросплатформой. S>2. Что же спрятано в WriteFile. S>Кстати, std::filesystem::copy_file грешит тем же самым!
S>while (!feof(источник)) { S> fread(buffer, источник); S> fwrite(buffer, приемник); S>} S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее) S>Размер буфера результатов на дал.
А ты не жалей. Не 1мб, а 16мб например используй
S>Почему?
fread/fwrite используют свои буфера. Юзай или open/read/write или если под винду CreateFile (если уж CopyFile-а не хочется).
Как много веселых ребят, и все делают велосипед...
Здравствуйте, Su34, Вы писали:
S>Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb!
Один килобайт — это ничтожно малый размер буфера для копирования сколько-нибудь объемных (хотя бы в единицы мегабайт) файлов. Хотите скорости — используйте хотя бы 64 кб, а для совсем уж больших файлов — 512-1024 кб.
S>1. Как быть с кросплатформой.
Использовать буферы адекватного размера.
S>2. Что же спрятано в WriteFile.
Вас это не должно интересовать, ибо fread/fwrite работают через ReadFile/WriteFile. То есть, все тормоза возникают выше.
Здравствуйте, ononim, Вы писали:
O>А ты не жалей. Не 1мб, а 16мб например используй
Под руками исходников stdio.h нет, но ЕМНИП там фиксированного (и небольшого) размера буфер, и указать свой его размер нельзя. Так что увеличение до 16 Мб приведет к противоположному эффекту — будет читаться в этот буфер кусками в его размер.
S>>Почему? O>fread/fwrite используют свои буфера. Юзай или open/read/write или если под винду CreateFile (если уж CopyFile-а не хочется).
PD>Под руками исходников stdio.h нет, но ЕМНИП там фиксированного (и небольшого) размера буфер, и указать свой его размер нельзя. Так что увеличение до 16 Мб приведет к противоположному эффекту — будет читаться в этот буфер кусками в его размер.
Почемуж нельзя, можно — setvbuf. И даже отключить можно буфер тот — setvbuf(.., _IONBF, 0) но там ведь еще и синхронизация своя имеется и тоже небольшие потери на нее будут. Вобщем, fopen&co это функции для парсинга и созданиявсяких там конфиг файлов, но не для bulk io, так сказать.
Как много веселых ребят, и все делают велосипед...