Скорость записи на flash.
От: Su34 Россия  
Дата: 23.10.24 13:33
Оценка:
Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель.
Пишу так (на С)
while (!feof(источник)) {
fread(buffer, источник);
fwrite(buffer, приемник);
}
источник — файл на диске, приемник файл на флешке.
Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее)
Размер буфера результатов на дал.
Почему?
Re: Скорость записи на flash.
От: kov_serg Россия  
Дата: 23.10.24 13:46
Оценка:
Здравствуйте, Su34, Вы писали:

S>Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель.

S>Пишу так (на С)
S>while (!feof(источник)) {
S> fread(buffer, источник);
S> fwrite(buffer, приемник);
S>}
S>источник — файл на диске, приемник файл на флешке.
S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее)
S>Размер буфера результатов на дал.
S>Почему?
Размер кратен 2^n ?
Re: Скорость записи на flash.
От: BlackEric http://black-eric.lj.ru
Дата: 23.10.24 13:50
Оценка: +1
Здравствуйте, Su34, Вы писали:

S>Неожиданно столкнулся с проблемой низкой скорости записи на flash-накопитель.

S>Пишу так (на С)
S>while (!feof(источник)) {
S> fread(buffer, источник);
S> fwrite(buffer, приемник);
S>}
S>источник — файл на диске, приемник файл на флешке.
S>Например, в TotalCommander, операция проходит в лет. (раз в 10-15 быстрее)
S>Размер буфера результатов на дал.
S>Почему?

Есть готовые функции в винде для копирования: CopyFileExA function (winbase.h)

Тотал скорее всего через них работает
https://github.com/BlackEric001
Re[2]: Скорость записи на flash.
От: Su34 Россия  
Дата: 23.10.24 13:59
Оценка:
Здравствуйте, 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);
Re[3]: Скорость записи на flash.
От: BlackEric http://black-eric.lj.ru
Дата: 23.10.24 14:14
Оценка:
Здравствуйте, 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);

Проблема точно в этом методе?
А покажите полный код метода.
https://github.com/BlackEric001
Re[3]: Скорость записи на flash.
От: kov_serg Россия  
Дата: 23.10.24 14:16
Оценка: +1
Здравствуйте, 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 и замените буфер просто случайными значениями.
Re[2]: Скорость записи на flash.
От: Su34 Россия  
Дата: 23.10.24 14:26
Оценка:
Здравствуйте, BlackEric, Вы писали:
BE>Есть готовые функции в винде для копирования: CopyFileExA function (winbase.h)
BE>Тотал скорее всего через них работает
Уходим за рамки раздела "Железо", но все же!
Если разделить процесс копирования файла на 2 потока, поток чтения и поток записи можно увеличить скорость копирования файла (для одного диска это эффекта не даст, будет даже обратный, а вот для разных устройств эффект есть). Я не думаю что CopyFileEx так сложно устроена!
Поэтому своя функция копирования.
Re[4]: Скорость записи на flash.
От: Su34 Россия  
Дата: 23.10.24 14:31
Оценка:
Здравствуйте, BlackEric, Вы писали:
BE>Проблема точно в этом методе?
BE>А покажите полный код метода.
clock_t rw_test(const char* from, const char* to, int block_size)
{
    FILE *src, *dst;
    if (fopen_s(&src, from, "rb"))
        return 0;
    if (fopen_s(&dst, to, "wb")) {
        fclose(src);
        return 0;
    }
    unsigned char *buf = (unsigned char*)malloc(block_size);
    clock_t start = clock();
    while (!feof(src)) {
        size_t result = fread(buf, 1, block_size, src);
        fwrite(buf, 1, result, dst);
    }
    clock_t stop = clock();
    free(buf);
    fclose(dst);
    fclose(src);
    return stop - start;
}

define from    "d:\\Soft\\Disk_Files\\Search\\FileBadgerSetup.msi"
#define to        "h:\\test.dat"

int main()
{
    int size[] = {1,1,2,4,8,16,32,64,512,1024,2048};
    for (auto n : size) {
        printf("%d kb - %d ms\n", n, rw_test(from, to, n*1024));
    return 0;
}
Re: Скорость записи на flash.
От: Stanislaw K СССР  
Дата: 23.10.24 14:36
Оценка:
Здравствуйте, 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 еще долго мигала после "окончания".

Far копирует более честно.
Все проблемы от жадности и глупости
Re[5]: Скорость записи на flash.
От: BlackEric http://black-eric.lj.ru
Дата: 23.10.24 14:37
Оценка:
Здравствуйте, Su34, Вы писали:

fread(buf, 1, block_size, src);

А не так:

fread(buf, sizeof(buf), block_size, src);

Почему там 1?
https://github.com/BlackEric001
Re: Скорость записи на flash.
От: TailWind  
Дата: 23.10.24 15:45
Оценка:
S>приемник файл на флешке.
USB-шной? ))
Ваша fwrite она блокирующая функция?
Ждёт завершения вероятно?
А у USB есть frame. Пока он не пройдёт подтверждение не получите

А что такие буферы маленькие?
Вы наверно издеваетесь

Вообще странный тест
Если проблема со скоростью записи
Не надо читать
Пишите в неё рандомный буфер
Замеряйте время

Сделайте тесты для разных размеров
Только не идиотксие 512 байт
Ну хотя бы 0x10000, 0x100000 байт

Сравните с виндовым FileWrite

Попробуйте файл целиком загрузить в память
И целиком записать. Ну 100МБ, например
Отредактировано 23.10.2024 15:56 TailWind . Предыдущая версия . Еще …
Отредактировано 23.10.2024 15:52 TailWind . Предыдущая версия .
Отредактировано 23.10.2024 15:49 TailWind . Предыдущая версия .
Отредактировано 23.10.2024 15:48 TailWind . Предыдущая версия .
Отредактировано 23.10.2024 15:47 TailWind . Предыдущая версия .
Re[6]: Скорость записи на flash.
От: Su34 Россия  
Дата: 23.10.24 16:19
Оценка:
Здравствуйте, 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 грешит тем же самым!
Re[7]: Скорость записи на flash.
От: BlackEric http://black-eric.lj.ru
Дата: 23.10.24 16:38
Оценка: :)
Здравствуйте, Su34, Вы писали:

S>Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb!

S>Меня это конечно удовлетворяет, но...
S>1. Как быть с кросплатформой.
S>2. Что же спрятано в WriteFile.
S>Кстати, std::filesystem::copy_file грешит тем же самым!

WriteFile асинхронная. Может быть причина в этом.
https://github.com/BlackEric001
Re[7]: Скорость записи на flash.
От: TailWind  
Дата: 23.10.24 16:50
Оценка: +1
S>Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb!

Смотрите флажки, которые кэша касаются

И 1КБ буфер это очень мало
Это два сектора всего
Отредактировано 23.10.2024 16:51 TailWind . Предыдущая версия .
Re: Скорость записи на flash.
От: mike_rs Россия  
Дата: 23.10.24 18:50
Оценка:
Здравствуйте, Su34, Вы писали:

S>Почему?

приемник открыт как non-cached
Отредактировано 23.10.2024 18:53 mike_rs . Предыдущая версия .
Re: Скорость записи на flash.
От: ononim  
Дата: 24.10.24 07:27
Оценка: +2
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-а не хочется).
Как много веселых ребят, и все делают велосипед...
Re[7]: Скорость записи на flash.
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.10.24 13:05
Оценка:
Здравствуйте, Su34, Вы писали:

S>Замена fwrite (7917 ms) на WriteFile(188 ms) дало ощутимый результат при буфере 1kb!


Один килобайт — это ничтожно малый размер буфера для копирования сколько-нибудь объемных (хотя бы в единицы мегабайт) файлов. Хотите скорости — используйте хотя бы 64 кб, а для совсем уж больших файлов — 512-1024 кб.

S>1. Как быть с кросплатформой.


Использовать буферы адекватного размера.

S>2. Что же спрятано в WriteFile.


Вас это не должно интересовать, ибо fread/fwrite работают через ReadFile/WriteFile. То есть, все тормоза возникают выше.
Re[8]: Скорость записи на flash.
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 24.10.24 13:06
Оценка:
Здравствуйте, BlackEric, Вы писали:

BE>WriteFile асинхронная.


Она может быть асинхронной, но CRT ее в этом режиме не использует.

BE>Может быть причина в этом.


Не может.
Re[7]: Скорость записи на flash.
От: Pavel Dvorkin Россия  
Дата: 24.10.24 13:22
Оценка:
Здравствуйте, Su34, Вы писали:

S>1. Как быть с кросплатформой.


Попробуй функции из io.h, то есть open — read — write

https://www.c-cpp.ru/content/open-rtlopen

S>2. Что же спрятано в WriteFile.


Ничего в ней не спрятано, кроме вызовов ядра Windows. А вот в stdio.h делается дополнительно буферизация средствами C, которая тут совсем не нужна.

open-read-write — без буферизации.
With best regards
Pavel Dvorkin
Re[2]: Скорость записи на flash.
От: Pavel Dvorkin Россия  
Дата: 24.10.24 13:34
Оценка:
Здравствуйте, ononim, Вы писали:

O>А ты не жалей. Не 1мб, а 16мб например используй


Под руками исходников stdio.h нет, но ЕМНИП там фиксированного (и небольшого) размера буфер, и указать свой его размер нельзя. Так что увеличение до 16 Мб приведет к противоположному эффекту — будет читаться в этот буфер кусками в его размер.

S>>Почему?

O>fread/fwrite используют свои буфера. Юзай или open/read/write или если под винду CreateFile (если уж CopyFile-а не хочется).

+1
With best regards
Pavel Dvorkin
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.