blu*_*lds 5 string performance java-7
我正在研究一个函数,它连续扫描大量相对较短的字符串,并从中生成大量子字符串。该函数将用于大容量字符串处理系统。我更喜欢首先优化内存,然后再优化 CPU,因为系统上的内存压力大于 CPU 压力。在这种情况下,性能如何比较:
//Java-ish PseudoCode
functionParent(List<String> strings) {
StringBuilder result;
for(String s : strings) {
result.appendAll(functionA(s));
}
}
functionA(String arg1) {
results.add(arg1.substring(i, i + length)); //hotspot here
}
Run Code Online (Sandbox Code Playgroud)
和:
//Java-ish PseudoCode
functionParent(List<String> strings) {
StringBuilder result;
for(String s : strings) {
result.appendAll(functionB(s.toCharArray()));
}
}
functionB(char[] arg1) {
results.add(new String(arg1,i, length)); //hotspot here
}
Run Code Online (Sandbox Code Playgroud)
据我到目前为止的测试来看,内存方面这是一次清洗(char[] 分配可以忽略不计并且不会影响 GC,两者都会创建相同数量的新字符串/ substring() 内存泄漏不久前已修复),并且由于不断查找子字符串,因此 char[] 版本在 CPU 方面获胜。这听起来正确吗?我的分析中是否遗漏了任何内容?
根据下面的答案,解决方案的注释
functionB似乎是最快的。另请注意, functionParent 中有一个 StringBuilder - 并且 StringBuilder 有一个 1append(char[], index, length)` 函数
如果您因String包含大量类似操作的操作而面临substring内存压力append,那么您应该意识到这种CharSequence抽象。许多 API 已经准备好使用这些来代替String.
由于String它本身实现了CharSequence,您可以更改您的方法来接受CharSequence输入,而不是String不改变它们的有用性。subSequencewill的实现String与substring,因此复制内容,但您可以创建一个子序列而不使用复制CharBuffer.wrap(string, start, end)。
如前所述,大多数操作都支持CharSequence输入,尤其是对于您的用例
StringBuilder.append(CharSequence s)StringBuilder.append(CharSequence s, int start, int end)已经提到过的CharBuffer.wrap(CharSequence csq, int start, int end)
还有\xe2\x80\x99s CharSequence.subSequence(int start, int end),但正如所说,如果底层序列是 aString你会得到一个副本,而CharBuffer.wrap保证非复制行为
CharBuffer.wrap(char[] array, int offset, int length)作为获取CharSequencea 表示的规范方法char[]作为无需复制即可获取数组String.contentEquals(CharSequence)Pattern.matcher(CharSequence)请注意,StringBuilder还实现了CharSequence,因此允许您的操作往返,而无需创建中间String副本。