关于Java IO性能调优的问题

时间:2011-01-17 12:30:41

标签: java performance

我正在尝试优化基于Web的应用程序,该应用程序会对流进行大量编写。 代码是这样的---

 StringWriter stringWriter = new StringWriter(1024);
 PrintWriter printWriter = new PrintWriter(stringWriter);

然后这个printwriter用于在几个地方做很多写操作,比如 -

 printWriter.write("set interface ethernet0 zone Trust");

我想通过将printwriter包装在bufferedwriter周围来优化几个写操作。所以我打算如下更改line1和line2。如果下面的方法是正确的,请告诉我 -

StringWriter stringWriter = new StringWriter(1024);
// go for bufferedwriter instead of printwriter.
BufferedWriter bufWriter = new BufferedWriter(stringWriter, 8*1024); 

另外,我认为现在我可以直接替换write方法,如 -

printWriter.write("set interface ethernet0 zone Trust");

替换为

bufWriter.write("set interface ethernet0 zone Trust");

如果这是正确的,请告诉我,或者我是否需要使用BufferedWriter的任何重载方法来充分利用BufferedWriter。

谢谢, 开发

4 个答案:

答案 0 :(得分:11)

由于StringWriter根据定义写入字符串缓冲区(在内存中),因此将其包装到BufferedWriter中不会对性能产生任何影响。 (由于额外的间接级别,它实际上可能会使您的代码变慢 - 尽管这个 可能最有可能被JIT编译器优化掉。)< / p>

后者在文件I / O中很有用,其中一次大写比几次小写快得多。

为什么你认为你需要调整这段代码?值得仔细阅读以下内容

关于性能调整的一般准则

  1. 不要这样做(你确定需要它吗?大部分时间你都不需要)。
  2. 不要这样做(Donald Knuth的相关经典语句:"Premature optimization is the root of all evil")。
  3. 不要优化您相信的代码< - > 使用分析器衡量效果 - 以找出实际的瓶颈。
  4. 在任何更改后再次进行测量,以验证您是否真正明显改善了性能(例如:很容易做出“聪明”的更改,这些更改没有任何差别,甚至会降低性能)

答案 1 :(得分:4)

添加BufferedWriter只会为每个写入的char添加额外的复制操作。你应该改变StringWriter的初始大小,更大的初始大小意味着更少的增长和更少的复制。

StringWriter本身包含一个不断增长的字符数据缓冲区,通过使用BufferedWriter在其上添加额外的缓冲区不会导致加速。从给定的代码中,StringWriter对象本身的较大初始大小可能会有所帮助。

答案 2 :(得分:3)

你真的需要使用StringWriter吗? StringWriter只是StringBuffer的一个代理,它会在每次调用append时自行同步。

您是否考虑过使用StringBuilder?它不是同步的(因此不是线程安全的),但应该更快 - 特别是如果你做了很多短写。

编辑:同步问题非常重要,因为PrintWriter也是同步的。每次调用print / write时,代码都必须获取并释放两个锁。我怀疑这可能就是为什么你的代码在write方法上花费了大量时间。

编辑: 如果你真的必须使用PrintWriter,那么下面的替代方案可以工作,但需要注意的是PrintWriter只能被一个线程访问 - 否则它可能会导致死锁。为了使这项工作顺利,所有写入必须在SAME同步块中执行,否则您将遇到同样的问题 - 例如进入和退出大量同步代码位。

    ByteArrayOutputStream out = new ByteArrayOutputStream(bufSize);

    PrintWriter writer = new PrintWriter(out);

    synchronized (writer) {
        // do writes
    }

    writer.flush(); // very important or you may not see any output in 'out'
    writer.close();

    String output = out.toString();

如果您不必使用PrintWriter,那么仅使用StringWriter即可。

    StringWriter writer = new StringWriter(bufSize);

    synchronized(writer.getBuffer()) {
        // do writes
    }

    writer.flush();
    writer.close();

    String output = writer.toString();

我的初步建议意味着什么:

    StringBuilder builder = new StringBuilder();

    // do APPENDS (instead of writes)

    String output = builder.toString();

你需要调用append而不是write,这就是你需要重构代码的原因。

答案 3 :(得分:0)

我真的怀疑BufferedWriter会在这里给予任何性能提升 - 它和StringWriter直接写入记忆。如果有的话,它会通过添加一个间接层来减慢(分数)的速度。当然,如果你发现不同,请纠正我。是什么让你认为这是一个瓶颈?