Java.io : 性能调优

11 浏览
0 Comments

Java.io : 性能调优

我有一个大约4MB的文件,这个文件是一个只包含普通键盘字符的ASCII文件。我尝试了java.io包中的许多类来将文件内容读取为字符串。逐个字符读取(使用FileReader和BufferedReader)大约需要40秒,使用java.nio包(FileChannel和ByteBuffer)读取内容大约需要25秒。根据我的了解,这个时间有点长。有人知道如何将这个时间减少到大约10秒左右吗?即使是使用C创建文件读取器并从Java调用的解决方案也可以。我使用下面的代码片段在22秒内读取了这个4MB的文件:\n

public static String getContents(File file) {
    try {
        if (!file.exists() && !file.isFile()) {
            return null;
        }
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        ByteBuffer buf = ByteBuffer.allocateDirect(512);            
        Charset cs = Charset.forName("ASCII");          
        StringBuilder sb = new StringBuilder();
        int rd;
        while ((rd = ch.read(buf)) != -1) {
            buf.rewind();
            CharBuffer chbuf = cs.decode(buf);
            for (int i = 0; i < chbuf.length(); i++) {
                sb.append(chbuf.get());
            }
            buf.clear();
        }
        String contents = sb.toString();
        System.out.println("File Contents:\n"+contents);
        return contents;
    } catch (Exception exception) {
        System.out.println("Error:\n" + exception.getMessage());
        return null;
    }
}

0
0 Comments

问题原因:使用较小的缓冲区大小导致性能下降。

解决方法:增加缓冲区大小,例如将其设置为2048或4096字节。

以下是一种可能的解决方法的实现示例:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 4096);

问题原因:使用本地API会导致无法利用Java的特性,如编译时类型检查。

解决方法:避免使用本地API,选择使用Java提供的API。

以下是一个示例,使用Java的API来读取文件:

BufferedReader br = new BufferedReader(new FileReader("file.txt"));

通过增加缓冲区大小和避免使用本地API,可以提高Java.io的性能。

0
0 Comments

Java.io : Performance Tuning

在进行Java IO性能调优时,出现了以下问题:

1. 在这里使用直接字节缓冲区没有任何好处。

2. 缓冲区大小为512太小了。至少使用4096。

3. 在这里使用NIO没有真正的好处。由于这是文本,我会使用BufferedReader。

4. 将整个文件读入内存的基本目标是有缺陷的。它不会扩展,并且已经使用了过多的内存。您应该设计一种逐行处理文件的策略。

针对上述问题,我们可以采取以下解决方法:

1. 不使用直接字节缓冲区。

2. 增加缓冲区大小至少为4096。

3. 使用BufferedReader代替NIO。

4. 设计一种逐行处理文件的策略,避免将整个文件读入内存,从而提高性能和可扩展性。

下面是一个示例代码,展示了如何使用BufferedReader逐行处理文件:

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        // 处理每一行数据
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

通过采取上述解决方法,我们可以更好地调优Java IO性能,提高程序的效率和可扩展性。

0
0 Comments

在上述内容中,出现了以下问题及解决方法:

问题:为什么在控制台上显示文件内容需要很长时间(40秒),而读取文件只需要很短的时间(小于1秒)?

解决方法:控制台更新屏幕的速度较慢,特别是在使用MS DOS控制台时。如果想要加快文件的读取速度,建议使用内存映射文件,但在这种情况下过于冗余。

问题:为什么在使用in.read(bytes)方法时,无法完全填充缓冲区?

解决方法:正确的做法是使用DataInputStream来读取文件,可以使用DataInputStream.readFully()方法。但是需要注意,该解决方法对于文件大小超过32位的情况不适用,而且不适用于一般情况下的扩展。

问题:在使用内存映射文件时,如何确保虚拟机会释放映射的字节缓冲区?

解决方法:在Sun/Oracle/OpenJDK中,可以通过使用内部API来实现释放映射字节缓冲区的操作。但是需要注意,并非所有情况下都能确保释放。

通过使用合适的读取文件的方法以及避免使用缓慢的控制台输出,可以提高Java.io性能。

0