Я работаю над довольно большим проектом на С++ уже несколько недель. Моя первоначальная цель состояла в том, чтобы использовать этот проект, чтобы узнать о С++ 11 и использовать только чистый код на С++ и избегать ручного распределения и конструкций C. Однако я думаю, что эта проблема заставит меня использовать C для небольшой функции, и я хотел бы знать, почему.
В принципе у меня есть функция сохранения, которая копирует несколько большой двоичный файл в отдельное место, прежде чем я вношу изменения в данные в нем. Сами файлы - это изображения компакт-дисков с максимальным размером около 700 МБ. Вот исходный код С++, который я использовал:
std::ios::sync_with_stdio(false);
std::ifstream in(infile, std::ios::binary);
std::ofstream out(outfile, std::ios::binary);
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(out));
out.close();
in.close();
Этот код при использовании с файлом 690 МБ занимает чуть менее 4 минут. Я запустил его с несколькими файлами, и это всегда тот же результат; ничего меньше 3 минут. Тем не менее, я также нашел следующий способ, который выполнялся немного быстрее, но все же нигде не так быстро, как C:
std::ios::sync_with_stdio(false);
std::ifstream in(infile, std::ios::binary);
std::ofstream out(outfile, std::ios::binary);
out << in.rdbuf();
out.close();
in.close();
Это заняло 24 секунды, но все равно примерно в 20 раз медленнее C.
Осмотревшись, я обнаружил, что кому-то нужно написать файл размером 80 ГБ и увидеть, что он может писать на полной скорости с помощью C. Я решил попробовать с этим кодом:
FILE *in = fopen(infile, "rb");
FILE *out = fopen(outfile, "wb");
char buf[1024];
int read = 0;
// Read data in 1kb chunks and write to output file
while ((read = fread(buf, 1, 1024, in)) == 1024)
{
fwrite(buf, 1, 1024, out);
}
// If there is any data left over write it out
fwrite(buf, 1, read, out);
fclose(out);
fclose(in);
Результаты были довольно шокирующими. Вот один из тестов, которые у меня есть после многократного запуска нескольких файлов:
File Size: 565,371,408 bytes
C : 1.539s | 350.345 MB/s
C++: 24.754s | 21.7815 MB/s - out << in.rdbuf()
C++: 220.555s | 2.44465 MB/s - std::copy()
В чем причина этой огромной разницы? Я знаю, что С++ не будет соответствовать производительности простого C, но разница в 348 МБ/с огромна. Что-то мне не хватает?
Edit:
Я компилирую это с помощью Visual Studio 2013 в 64-разрядной ОС Windows 8.1.
Изменить 2:
После прочтения ответа Джона Звинка я решил просто перейти на конкретный маршрут платформы. Поскольку я все еще хотел сделать свою кросс-платформу проекта, я собрал быстрый пример. Я действительно не уверен, работают ли они в других системах помимо Windows, но я могу проверить Linux на более поздний срок. Я не могу проверить OSX, но я думаю, что copyfile выглядит как простая функция, поэтому я предполагаю, что это правильно.
Имейте в виду, что вам нужно сделать одну и ту же логику #ifdef для включения заголовков конкретной платформы.
void copy(std::string infile, std::string outfile)
{
#ifdef _WIN32 || _WIN64
// Windows
CopyFileA(infile.c_str(), outfile.c_str(), false);
#elif __APPLE__
// OSX
copyfile(infile.c_str(), outfile.c_str(), NULL, COPYFILE_DATA);
#elif __linux
// Linux
struct stat stat_buf;
int in_fd, out_fd;
offset_t offset = 0;
in_fd = open(infile.c_str(), O_RDONLY);
fstat(in_fd, &stat_buf);
out_fd = open(outfile.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode);
sendfile(out_fd, in_fd, &offset, stat_buf.st_size);
close(out_fd);
close(in_fd);
#endif
}