我正在尝试将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%工具。
我只想将文件读入内存,以便以后我可以更快地从内存中访问我想要的数据。我是以正确的方式做的吗?谢谢!
答案 0 :(得分:1)
首先,Java以UTF-16存储字符串,因此如果您的输入文件主要包含latin-1符号,那么您将需要两倍的内存来存储这些符号,因此1Gb用于存储字符。其次,每条线路都有开销。我们可能粗略估计一下:
ArrayList
到String
的引用 - 4个字节(假设是压缩的oops)String
到char[]
数组的引用 - 4个字节String
对象标题 - 至少8个字节hash
字符串字段(存储hashCode) - 4个字节char[]
对象标题 - 至少8个字节char[]
数组长度 - 4个字节因此,每行至少会浪费32个字节。通常情况下,必须填充对象。因此,对于20_000_000行,开销至少为640_000_000字节。