StringBuilder最有效的初始容量大小?

我正在写很多东西来登录突发,并优化数据路径。 我用StringBuilder构建日志文本。 什么是最有效的初始容量,内存管理明智,所以无论JVM如何都能很好地工作? 目标是避免几乎总是重新分配,这应该由初始容量约80-100覆盖。 但是我也想浪费尽可能少的字节,因为StringBuilder实例可能会在缓冲区中出现并且会浪费掉浪费的字节。

我意识到这取决于JVM,但是应该有一些值,这会浪费最少的字节,无论JVM,都是“最小公分母”。 我目前正在使用128-16 ,其中128是一个很好的整数,减法用于分配开销。 此外,这可能被视为“过早优化”的情况,但由于我所追求的答案是一个“经验法则”数字,因此知道它在将来也会有用。

我不期待“我最好的猜测”答案(上面我自己的答案已经是这样),我希望有人已经研究过这个并且可以分享基于知识的答案。

在这种情况下,不要试图变得聪明。

我目前正在使用128-16,其中128是一个很好的整数,减法用于分配开销。

在Java中,这是基于对JVM内部工作的完全任意的假设。 Java不是C.字节对齐等绝对不是程序员可以或应该尝试利用的问题。

如果您知道字符串的(可能的)最大长度,则可以将其用作初始大小。 除此之外,任何优化尝试都是徒劳的。

如果你真的知道你的大量StringBuilder将会存在很长时间(这不太符合日志记录的概念),你真的觉得需要尝试说服JVM来节省一些字节的堆空间你完全构建字符串后,可以尝试使用trimToSize() 。 但是,同样,只要你的字符串不浪费兆字节,你就应该专注于应用程序中的其他问题。

好吧,我最后自己对此进行了简要的测试,然后在评论之后再测试一下,以获得这个编辑过的答案。

使用JDK 1.7.0_07和测试应用程序报告VM名称“Java HotSpot(TM)64位服务器VM”, StringBuilder内存使用的粒度为4个字符 ,甚至在4个字符处增加。

答:从内存分配的角度来看, 任何4的倍数对于StringBuilder来说都是同样好的容量,至少在这个64位JVM上是这样。

通过在不同的测试程序执行中创建具有不同初始容量的1000000个StringBuilder对象(具有相同的初始堆状态),并在之前和之后打印出ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()

打印出堆大小也证实了,每个StringBuilder缓冲区实际从堆中分配的数量是8个字节的偶数倍,正如预期的那样,因为Java char是2个字节长。 换句话说,分配初始容量为1..4的1000000个实例需要大约8兆字节的内存(每个实例8个字节),而不是分配初始容量为5 … 8的相同数量的数据。