将数据读取到内存java中的性能

将数据读取到内存java中的性能,java,memory,io,jvm,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>(); Syst

我正在尝试将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);
    }
}
String url_part=“/homes/t1.csv”;
文件f=新文件(url\u部分);
BufferedReader br=新的BufferedReader(新的InputStreamReader(新文件InputStream(f));
ArrayList mem=新的ArrayList();
System.out.println(“开始加载…”);
gc();
双启动=System.currentTimeMillis();
String line=br.readLine();
整数计数=0;
while(行!=null){
line=br.readLine();
成员添加(行);
//系统输出打印项次(计数);
计数++;
如果(计数%500000==0){
系统输出打印项次(计数);
}
}
该文件包含40000000行,在读取18500000行之前,性能完全良好,但在读取大约20000000行之后,它会在某个地方出现问题。(此处冻结,但经过长时间等待,大约10秒后继续)


我跟踪了内存使用情况,发现即使文件的总大小只有512MB,运行程序时内存也会增加2GB左右。此外,8核CPU保持100%UTIL工作


我只想把文件读入内存,这样以后我可以更快地从内存中访问我想要的数据。我这样做对吗?谢谢!

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

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

因此,每行至少浪费32字节。通常情况下,它更多的是因为必须填充对象。因此,对于20_000_000行,您至少有640_000_000字节的开销。

“我发现即使文件的总大小只有512 MB,运行程序时内存也会增长约2GB”-这并不奇怪。你有a)字符串对象、数组等的开销——如果每个字符串只有大约25个字符,这很可能是非常重要的;b) 假设文件是用ASCII或其他每字符1字节的编码方式编码的,由于在Java中使用UTF-16,您得到了一个2倍的放大倍数。这似乎是一个错误。@JonSkeet感谢您的回复!但关键是为什么程序会在某个时候卡住?它以前读得很流畅,但后来运行得越来越慢。我怀疑它试图分配更多内存。你的机器有多少内存,你让Java有多少内存?(例如java-Xmx4G…@fTTTTT垃圾收集是另一个可能的罪魁祸首。感谢您的回答。但在这种情况下,高效存储字符串对象数组的最佳解决方案是什么?通常没有人在内存中存储如此大的文件。您可能应该逐行或按块处理它,或者导入到一些DBMS中,并使用DBMS查询来处理它。