大家下午好,我正在使用 java.lang.StringBuilder存储一些字符。我不知道我要提前存储多少个字符,除了:
- 60% 的情况下,它只有(恰好)7 个字符
- 39% 的时间是(大约)3500 个字符
- 1% 的时间,大约是 20k 个字符
我们如何计算应该使用的最佳初始缓冲区长度?
目前我正在使用 new java.lang.StringBuilder(4000)
但那只是因为我以前懒得想。
最佳答案
这里有两个因素:时间和内存消耗。该时间主要受 java.lang.AbstractStringBuilder.expandCapacity()
调用次数的影响。当然,每次调用的成本与缓冲区的当前大小成线性关系,但我在这里进行了简化,只是计算它们:
expandCapacity()
的次数(时间)
默认配置(16个字符容量)
- 在 60% 的情况下,
StringBuilder
将展开 0 次 - 在 39% 的情况下,
StringBuilder
会扩展 8 倍 - 在 1% 的情况下,
StringBuilder
会扩展 11 倍
expandCapacity
的预期数量是 3,23。
初始容量4096个字符
- 在 99% 的情况下,
StringBuilder
将展开 0 次 - 在 1% 的情况下,
StringBuilder
会扩展 3 倍
expandCapacity
的预期数量是 0,03。
如您所见,第二种情况似乎要快得多,因为它很少需要扩展 StringBuilder
(每 100 个输入三次)。但是请注意,第一次扩展不太重要(复制少量内存);此外,如果您以大块的形式向构建器添加字符串,它将在更少的迭代中更急切地扩展。
另一方面,内存消耗增长:
内存消耗
默认配置(16个字符容量)
- 在 60% 的情况下,
StringBuilder
将占用 16 个字符 - 在 39% 的情况下,
StringBuilder
将占用 4K 个字符 - 在 1% 的情况下,
StringBuilder
将占用 32K 个字符
预期的平均内存消耗为:1935 个字符。
初始容量4096个字符
- 在 99% 的情况下,
StringBuilder
将占用 4K 个字符 - 在 1% 的情况下,
StringBuilder
将占用 32K 个字符
预期的平均内存消耗为:4383 个字符。
长话短说
这让我相信,将初始缓冲区扩大到 4K 将使内存消耗增加两倍以上,同时将程序加速两个数量级。
底线是:尝试!编写一个基准程序来处理具有不同初始容量的各种长度的数百万个字符串并不难。但我相信更大的缓冲区可能是一个不错的选择。
关于java - 对于长度变化很大的输入,最佳 StringBuffer 初始容量是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8953418/