Самый быстрый способ сохранить большие данные в файл

StackOverflow https://stackoverflow.com/questions/4102202

Вопрос

Я делаю некоторые численные расчеты в 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 строк. Это приводит меня к вопросам:

  1. Может ли пример C ++ быть быстрее?
  2. Должен ли я использовать StringBuilder для Java или, может быть, это также плохо из -за количества строк
  3. Есть какой -нибудь другой путь или библиотека?
  4. А как насчет 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 и профиль беспощадно

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top