java StringBuilder 最有效的初始容量大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13360229/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Most efficient initial capacity size for StringBuilder?
提问by hyde
I'm writing lots of stuff to log in bursts, and optimizing the data path. I build the log text with StringBuilder
. What would be the most efficient initial capacity, memory management wise, so it would work well regardless of JVM? Goal is to avoid reallocation almost always, which should be covered by initial capacity of around 80-100. But I also want to waste as few bytes as possible, since the StringBuilder instance may hang around in buffer and wasted bytes crop up.
我正在写很多东西来登录突发,并优化数据路径。我用StringBuilder
. 什么是最有效的初始容量,明智的内存管理,无论 JVM 是什么,它都能很好地工作?目标是几乎总是避免重新分配,这应该由大约 80-100 的初始容量覆盖。但我也想尽可能少地浪费字节,因为 StringBuilder 实例可能会在缓冲区中徘徊并且浪费的字节会突然出现。
I realize this depends on JVM, but there should be some value, which would waste least bytes, no matter the JVM, sort of "least common denominator". I am currently using 128-16
, where the 128 is a nice round number, and subtraction is for allocation overhead. Also, this might be considered a case of "premature optimization", but since the answer I am after is a "rule-of-a-thumb" number, knowing it would be useful in future too.
我意识到这取决于 JVM,但应该有一些价值,这会浪费最少的字节,无论 JVM,有点“最小公分母”。我目前正在使用128-16
,其中 128 是一个不错的整数,减法用于分配开销。此外,这可能被认为是“过早优化”的一种情况,但由于我所追求的答案是“经验法则”数字,因此知道它将来也会有用。
I'm not expecting "my best guess" answers (my own answer above is already that), I hope someone has researched this already and can share a knowledge-based answer.
我不期待“我最好的猜测”答案(我上面的答案已经是这样),我希望有人已经对此进行了研究并且可以分享基于知识的答案。
采纳答案by hyde
Well, I ended up testing this briefly myself, and then testing some more after comments, to get this edited answer.
好吧,我最终自己简单地测试了这个,然后在评论后测试了更多,以获得这个编辑过的答案。
Using JDK 1.7.0_07 and test app reporting VM name "Java HotSpot(TM) 64-Bit Server VM", granularity of StringBuilder
memory usage is 4 chars, increasing at even 4 chars.
使用 JDK 1.7.0_07 和测试应用程序报告 VM 名称“Java HotSpot(TM) 64-Bit Server VM”,StringBuilder
内存使用粒度为 4 个字符,甚至增加到 4 个字符。
Answer: any multiple of 4is equally good capacity for StringBuilder from memory allocation point of view, at least on this 64-bit JVM.
答:从内存分配的角度来看,4 的任何倍数对于 StringBuilder 来说都是同样好的容量,至少在这个 64 位 JVM 上是这样。
Tested by creating 1000000 StringBuilder objects with different initial capacities, in different test program executions (to have same initial heap state), and printing out ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()
before and after.
通过创建 1000000 个具有不同初始容量的 StringBuilder 对象进行测试,在不同的测试程序执行中(具有相同的初始堆状态),并在ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed()
前后打印出来。
Printing out heap sizes also confirmed, that amount actually allocated from heap for each StringBuilder
's buffer is an even multiple of 8 bytes, as expected since Java char is 2 bytes long. In other words, allocating 1000000 instances with initial capacity 1..4 takes about 8 megabytes less memory (8 bytes per instace), than allocating same number of isntances with initial capacity 5...8.
打印出堆大小也证实,实际从堆分配给每个StringBuilder
缓冲区的数量是 8 字节的偶数倍,正如预期的那样,因为 Java char 是 2 字节长。换句话说,分配 1000000 个初始容量为 1..4 的实例比分配相同数量的初始容量为 5...8 的实例占用的内存少 8 兆字节(每个实例 8 字节)。
回答by JimmyB
Don't try to be smart in this case.
在这种情况下,不要试图变得聪明。
I am currently using 128-16, where the 128 is a nice round number, and subtraction is for allocation overhead.
我目前使用的是 128-16,其中 128 是一个不错的整数,减法用于分配开销。
In Java, this is based on totally arbitrary assumptions about the inner workings of a JVM. Java is not C. Byte-alignment and the like are absolutely notan issue the programmer can or should try to exploit.
在 Java 中,这是基于对 JVM 内部工作的完全武断的假设。Java 不是 C。字节对齐等绝对不是程序员可以或应该尝试利用的问题。
If you know the (probable) maximum length of your strings you may use that for the initial size. Apart from that, any optimization attempts are simply in vain.
如果您知道字符串的(可能的)最大长度,您可以将其用于初始大小。除此之外,任何优化尝试都是徒劳的。
If you really knowthat vast amounts of your StringBuilder
s will be around for very long periods (which does not quite fit the concept of logging), andyou really feel the need to try to persuade the JVM to save some bytes of heap space you may try and use trimToSize()
after the string is built completely. But, again, as long as your strings don't waste megabytes each you really should go and focus on other problems in your application.
如果您真的知道大量的StringBuilder
s 将存在很长时间(这不太符合日志记录的概念),并且您真的觉得有必要尝试说服 JVM 节省一些字节的堆空间,您可能会trimToSize()
在字符串完全构建后尝试使用。但是,同样,只要您的字符串不浪费每个兆字节,您就应该专注于应用程序中的其他问题。