2015-07-27 4 views
1

Я пытаюсь прочитать 512 МБ-файл в java-памяти. Вот мой код:Производительность при чтении данных в память java

String url_part = "/homes/t1.csv"; 
File f = new File(url_part); 
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f))); 
    ArrayList<String> mem = new ArrayList<String>(); 
System.out.println("Start loading....."); 
System.gc(); 
double start = System.currentTimeMillis(); 
String line = br.readLine(); 
int count = 0; 
while(line!=null){ 
    line=br.readLine(); 
    mem.add(line); 
    //System.out.println(count); 
    count++; 
    if(count%500000==0){ 
     System.out.println(count); 
    } 
} 

Файл содержит 40000000 линии, производительность совершенно нормально перед чтением 18500000 строк, но это заклинивание где-то после прочтения около 20000000 строк. (Он замораживается здесь, но продолжается после долгого ожидания, около 10 секунд)

Я отслеживал использование памяти, я нашел, что даже общий размер файла составляет всего 512 МБ, при работе программы память растет примерно на 2 ГБ. Кроме того, 8-ядерный процессор продолжает работать на 100% -ном уровне.

Я просто хочу прочитать файл в памяти, чтобы позже я смог получить доступ к данным, которые я хочу быстрее из памяти. Правильно ли я делаю? БЛАГОДАРЮ!

+1

«Я нашел, что даже общий размер файла составляет всего 512 МБ, при работе программы память составляет около 2 ГБ» - это не огромный сюрприз. У вас есть a) накладные расходы на строковые объекты, массивы и т. Д. - если каждая строка содержит всего около 25 символов, это, возможно, значимо; б) предполагая, что файл закодирован в ASCII или какой-либо другой кодировке с 1 байтом на символ, у вас есть коэффициент два раздутия только из-за использования UTF-16 в Java. –

+0

Это похоже на проблему [XY] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – biziclop

+0

@JonSkeet Спасибо за ответ! Но ключ в том, почему программа застряла в какой-то момент? Он читал гладко раньше, но работает медленнее и медленнее. – fTTTTT

ответ

1

Во-первых, Java хранит строки в UTF-16, поэтому, если ваш входной файл содержит в основном символы латинского-1, вам потребуется в два раза больше памяти для хранения этих символов, таким образом, 1Gb используется для хранения символов. Во-вторых, на каждую линию приходится накладные расходы. Мы можем грубо оценить его:

  • Справка с ArrayList к String - 4 байта (предполагается, что сжатый упс)
  • Справка с String до char[] массива - 4 байта
  • заголовка String объекта - по крайней мере, 8 байт
  • hash Строковое поле (для хранения hashCode) - 4 байта
  • char[] заголовок объекта - не менее 8 байт
  • char[] длина массива - 4 байта

Таким образом, по крайней мере 32 байта будут потрачены впустую на каждую строку. Обычно это больше, поскольку объекты должны быть дополнены. Итак, для 20_000_000 строк у вас есть как минимум 640_000_000 байт.

+0

Спасибо за ответ. Но в таком случае было бы лучшим решением для эффективного хранения массива строкового объекта? – fTTTTT

+0

Обычно в памяти нет таких больших файлов. Вы, вероятно, должны обрабатывать его по очереди или кусками или импортировать в некоторые СУБД и использовать запросы СУБД для его обработки. –