Java 优化编写StringBuilder';s内容到ServletResponse

Java 优化编写StringBuilder';s内容到ServletResponse,java,jakarta-ee,response,stringbuilder,servlet-3.0,Java,Jakarta Ee,Response,Stringbuilder,Servlet 3.0,我想获得一些关于优化我的方法的意见,这些方法是为将StringBuilder的全部内容写入ServletResponse而创建的 我这样做是为了避免在传递给out.write()方法之前一次性创建巨大的字符串。在我的情况下,StringBuilder的内容长度有时达到几百万个字符 public static void writeResponse(ServletResponse response, StringBuilder sb) throws IOException { try (Pr

我想获得一些关于优化我的方法的意见,这些方法是为将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));
            }
        }
    }
}
公共静态void writeResponse(ServletResponse,StringBuilder sb)引发IOException{
尝试(PrintWriter out=response.getWriter()){
int length=sb.length();
//为了避免创建巨大的字符串,我们正在从sb中编写子字符串
int bufferSize=(response.getBufferSize()!=0?response.getBufferSize():10000);
log.log(Level.INFO,“准备发送到客户端,响应的长度={0}”,长度);
如果(长度最快的方法是:

out.write(sb.toString());
如果要节省内存,请将
StringBuilder
替换为
PrintWriter
并传递
response.getWriter()

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

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

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

如果要保留
StringBuilder
,请找出页面的大小,并创建一个非默认大小的
StringBuilder
,这样它就不必一直扩展其内部缓冲区。

最快的方法是:

out.write(sb.toString());
如果要节省内存,请将
StringBuilder
替换为
PrintWriter
并传递
response.getWriter()

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

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

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


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

我认为您不必担心缓冲区的大小。让容器来做吧。@mKorbel也很高兴见到您。我知道,有很多变化你看,自从上次我们见面以来,你获得了100%以上的代表权。我的祝贺。干得好。它的大部分还是集中在
swing
部分SO:)我认为你不应该担心缓冲区的大小。让容器来做吧。@mKorbel也很高兴见到你。我知道,自从上次我们见面以来,发生了很多变化。你获得了大约100%的代表。我祝贺你。干得好。大部分信息还是在
swing
部分收集的吗:)谢谢你的回复(+1)。我知道
out.write(sb.toString());
是最快的,就像你说的,它是一个内存杀手。你能解释一下你的意思吗:
如果你想节省内存,用PrintWriter替换StringBuilder并传递响应。getWriter()大约。
?您的意思是为了节省内存,我应该直接写入响应吗?是的。响应将收集输出,直到缓冲区已满。这意味着:您不必保留数据,浏览器将在您从servlet返回之前开始接收数据。而且由于TCP/IP发送的字节数不能超过1500/8000字节不管你是否想要,每个数据包的数据量都将被切碎。注意:始终传递writer,而不是response对象。这样,你可以在单元测试中轻松测试代码。+1用于传递writer。从根本上切断问题。尽管这几乎肯定会发送一个分块响应。还要注意t
Writer
StringBuilder
都实现了
appendeable
接口,因此您可以传递appendeable来进一步减少耦合。感谢您的响应(+1)。我知道
out.write(sb.toString());
作为最快的,正如你所说,它是一个内存杀手。你能解释一下你的意思吗:
如果你想节省内存,用PrintWriter替换StringBuilder并传递响应。getWriter()大约。
?您的意思是为了节省内存,我应该直接写入响应吗?是的。响应将收集输出,直到缓冲区已满。这意味着:您不必保留数据,浏览器将在您从servlet返回之前开始接收数据。而且由于TCP/IP发送的字节数不能超过1500/8000字节不管你是否想要,每个数据包的数据量都将被切碎。注意:始终传递writer,而不是response对象。这样,你可以在单元测试中轻松测试代码。+1用于传递writer。从根本上切断问题。尽管这几乎肯定会发送一个分块响应。还要注意t
Writer
StringBuilder
都实现了
appendeable
接口,因此可以传递appendeable来进一步减少耦合。