读取数据到内存java的性能

时间:2015-07-27 15:09:32

标签: java memory io jvm

我正在尝试将512MB文件读入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 MB,运行程序时内存增长约2GB。此外,8核CPU保持100%工具。

我只想将文件读入内存,以便以后我可以更快地从内存中访问我想要的数据。我是以正确的方式做的吗?谢谢!

1 个答案:

答案 0 :(得分:1)

首先,Java以UTF-16存储字符串,因此如果您的输入文件主要包含latin-1符号,那么您将需要两倍的内存来存储这些符号,因此1Gb用于存储字符。其次,每条线路都有开销。我们可能粗略估计一下:

  • ArrayListString的引用 - 4个字节(假设是压缩的oops)
  • Stringchar[]数组的引用 - 4个字节
  • String对象标题 - 至少8个字节
  • hash字符串字段(存储hashCode) - 4个字节
  • char[]对象标题 - 至少8个字节
  • char[]数组长度 - 4个字节

因此,每行至少会浪费32个字节。通常情况下,必须填充对象。因此,对于20_000_000行,开销至少为640_000_000字节。