Самый быстрый способ сохранить большие данные в файл
-
29-09-2019 - |
Вопрос
Я делаю некоторые численные расчеты в Java, C # и C ++. Некоторые из них сохраняют много данных (к текстовому файлу). Какой самый быстрый способ сделать это?
C ++.
ofstream file;
file.open(plik);
for(int i=0;i<251;i++){
for(int j=0;j<81;j++)
file<<(i-100)*0.01<<" "<<(j-40)*0.01<<" "<<U[i][j]<<endl;
file<<endl;
}
Что я предполагаю, очень быстро (я прав? :))
Джава
void SaveOutput(double[][] U, String fileName) throws IOException
{
PrintWriter tx = new PrintWriter(new FileWriter(fileName));
for(int i=0;i<251;i++)
{
for(int j=0;j<81;j++)
{
tx.println(String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]));
}
tx.println();
}
tx.close();
}
Пример C # похож.
И вот что меня беспокоит. Я делаю строковый объект для каждой строки (много мусора). В этом примере это не так много, но иногда у меня 10 000 000 строк. Это приводит меня к вопросам:
- Может ли пример C ++ быть быстрее?
- Должен ли я использовать StringBuilder для Java или, может быть, это также плохо из -за количества строк
- Есть какой -нибудь другой путь или библиотека?
- А как насчет C#?
Спасибо
Решение
Профиль это. Запустите код, время, посмотрите, сколько времени это займет. Если количество времени, которое необходимо, приемлемо, используйте его. Если нет, выясните, какой кусок затрагивает длительное количество времени, и оптимизируйте его.
- Сделать это правильно.
- Сделай это быстро.
Этот заказ. (Некоторые люди добавляют «запустить/строить» перед этими двумя ...)
Тем не менее, я на самом деле запускал метрики на таких вещах раньше. В конце концов: вы ждете диска, а диск нечестно медленный. Неважно, пишете ли вы в C или C ++ или Java, они все ждут жесткого диска.
Вот а предыдущий пост То, что я сделал на различных методах ввода/вывода в C. Не совсем то, что вы ищете, но могут быть информативными.
Другие советы
Одно слово: профиль.
Обратите внимание, что вставка std::endl
Для буферизованного (файлового) потока заставляет его промыть, что, вероятно, ухудшит производительность (из языкового POV это означает, что буфер написан «выезд», хотя это не обязательно означает доступ к физическому диску). Для простой печати Newline, используйте '\n'
- Это никогда не хуже.
Во-первых, и прежде всего: используйте буферный писатель!
Это может включать в себя включение буферизации на канале на некоторых языках или использование BufferedWriter (в Java) или эквивалент в других. Неспособность сделать это может привести к далеко недневной производительности Поскольку выходной поток может быть «перевернут»-примерный код примеры нарушает это (файл-автор ничего не знает о буферизации)!
Во многих случаях можно рассматривать процессору и основную доступ к памяти «дешево» и ввода -вывода «дорогостоящим» - в таких тривиальных случаях, как это, улучшение доступа к самому вводу (например, буферизацию, а не [над] промывками) приведет к наибольшему количеству осязаемые достижения. Современные виртуальные машины и JIT делают то, что они делают довольно хорошо, и распределение объектов/распределение объектов, вероятно, является наименьшим из «забот» здесь.
Сначала обратите внимание, что эта программа ввода / вывода будет не значительно улучшать, в зависимости от небольшой детализации (например, если вы используете потоки C ++ или printf
).
Для части C/C ++ некоторые говорят, что используя OL ' printf
Операции быстрее. Это мая Будь быстрее, но не так приказы, поэтому я не буду беспокоиться.
Что касается версии Java, я думаю, что она уже довольно оптимизирована.
Не могу сказать для C #, мой доктор не позволяет мне :)
Вместо этого используйте класс java.nio для создания каналов. Каналы являются новыми для Java и намного быстрее, чем старые потоки. Вы также должны буферизировать запись. Я не могу вспомнить, если по умолчанию буферизируйте каналы. Мне нужно прочитать что -то, чтобы сказать вам это.
Наконец, все в порядке, вы создаете много строки. Вы бросаете их мгновенно. Я сомневаюсь, что это сделает вашу запись на диск медленно. Диск IO намного медленнее, чем ЦП.
Вот о чем я думал:
fileChannel = new FileOutputStream("test.txt").getChannel();
for(int i=0;i<251;i++) {
for(int j=0;j<81;j++) {
fileChannel.write(ByteBuffer.wrap((String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]) + "\n").toBytes());
}
fileChannel.close();
Я ожидаю, что будет быстрее использовать fprintf
в C или C ++.
Лукас,
Во -первых, я знаю в основном C#, так что все здесь относится к .NET.
С номером строк, с которыми вы имеете дело, я бы не создал строки или использовать StringBuilder. StringBuilder помогает только с созданием строк из ряда меньших сегментов.
Я думаю, что лучше всего использовать потоковые версии объектов файловой системы. Таким образом, вы вообще не храните струны, и поэтому использование вашей памяти должно быть довольно маленьким.
Кроме того, если у вас действительно мало памяти, вы всегда можете создать неуправляемую строку и P/вызвать в нее.
Erick.
Что касается Java, вам не нужно создавать все эти строки. Избавиться от String.format
и напишите байты напрямую.
Используйте NIO и профиль беспощадно