优化将StringBuilder的内容写入ServletResponse

时间:2012-03-08 13:13:28

标签: java java-ee response stringbuilder servlet-3.0

我想获得一些关于优化我为将StringBuilder的整个内容写入ServletResponse而创建的方法的注释。

我这样做是为了避免在将它传递给out.write()方法之前一次性创建巨大的字符串。在我的情况下,StringBuilder的内容长度在某些情况下会达到几百万个字符。

public static void writeResponse(ServletResponse response, StringBuilder sb) throws IOException {
    try (PrintWriter out = response.getWriter()) {
        int length = sb.length();
        //to avoid creation of gigantic strings we are writing substrings from the sb 
        int bufferSize = (response.getBufferSize() != 0? response.getBufferSize():10000);
        log.log(Level.INFO, "READY TO SEND To CLIENT, length of responseSB={0}", length);
        if (length <= bufferSize) {
            out.write(sb.toString());
        } else {
            int noWrites = length / bufferSize;
            for (int i = 0; i < noWrites; i++) {
                out.write(sb.substring(i * bufferSize, (i + 1) * bufferSize));
                log.log(Level.INFO, "SENDING To CLIENT, write no={0} of {1}", new Object[]{(i + 1), noWrites});
            }
            int rest = length % bufferSize;
            if (rest != 0) {
                out.write(sb.substring(length - rest, length));
            }
        }
    }
}

我想要它写一个(不是分块的)消息。因此,我想知道如何准确地建立响应缓冲区大小相对于它可以适合的多个字符(或字符串的长度)?

目前,我正在使用当前缓冲区大小并使用它,好像它表达了它可以容纳的一些字符,如何正确评估缓冲区大小?此外,我不是包括标题大小,我怎么能实现它?

我想将其性能优化到最大(因此工作速度最快),我们非常感谢任何建议。或者也许有一种更好的方法可以将巨大的StringBuilder内容写入ServletResponse?

1 个答案:

答案 0 :(得分:4)

最快的方法是:

out.write(sb.toString());

如果您想节省内存,请将StringBuilder替换为PrintWriter并传递response.getWriter()

关于缓冲区大小的任何优化只会使事情变慢。如果没有优化,成本大致为:StringBuilder.toString() + out.write(),它将长字符串传递给容器以进行分块/发送。

通过优化,它看起来像这样:StringBuilder.toString() + substring() + out.write() +将子字符串复制到发送缓冲区+许多调用容器来发送碎片。

如果你摆脱了构建器,对容器的调用次数将保持不变(out.write()使用内部缓冲区)但你不会浪费内存来保存数据。

如果你想保留StringBuilder,那么找出页面的大小,并创建一个非默认大小的StringBuilder,这样它就不必扩展它的内部缓冲区了时间。