Che*_*nhe 1 string stringbuilder android garbage-collection kotlin
我的目标是简单地替换子字符串,但非常频繁。该程序在Android中运行。
比如我有一个 string ={a} is a good {b}.和一个 map= {{a}=Bob, {b}=boy},结果应该是Bob is a good boy.我需要处理不同字符串的这种替换最多 400 次对等秒,因为 map 的值会实时更新。
但是我使用 trie 树和 Aho-Corasick 自动机来获得高性能,这是核心片段:
val builder: StringBuilder
private fun replace(str: String): String {
if (!getFail) {
getFail()
}
var p = 1
builder.setLength(0)
for (c in str) {
builder.append(c)
if (c.toInt() !in 0..126) {
continue // ignore non-ascii char
}
var k = trie[p][c.toInt()]
while (k > 1) {
// find a tag
if (end[k] != 0) {
val last = builder.length - end[k]
// replace the tag
values[builder.sub(last, end[k])]?.let {
builder.replace1(last, end[k], it)
}
p = 0
break
}
k = fail[k] // not find
}
p = trie[p][c.toInt()]
}
return builder.toString()
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我已经习惯StringBuilder了重用内存,但最后我不得不调用StringBuilder.toString()返回结果,这个操作创建了一个新的字符串对象。同时结果的生命周期很短,替换函数被频繁调用。因此,JVM 会频繁地进行 GC。
有什么方法可以重用短寿命结果字符串占用的内存?或者只是其他一些解决方案。
有什么方法可以重用短寿命结果字符串占用的内存?
不。
或者只是其他一些解决方案。
如果您可以更改使用String此方法生成的对象的代码以接受 a CharSequence。然后你可以将它的StringBuilder实例传递给builder,并避免toString()调用。
问题是,你将无法阻止的东西从铸造CharSequence到StringBuilder和变异它。(但如果代码不是安全关键的,你可以忽略它。意外地很难做到这一点,特别是如果你CharSequence在传递时使用接口类型StringBuilder。)
另一个问题是调用者实际上每次都会以不同的状态获取相同的对象。它无法保持状态……除非它要求toString()它。
但是您可能会不必要地担心性能。GC 比较擅长处理生命周期较短的对象。假设一个对象在创建后的第一个 GC 周期中无法访问,它永远不会被标记或复制,删除它的成本将为零。粗略估计,“来自”空间中的可到达对象将花费您。
我会首先做一些分析和 GC 监控。如果有明确的证据表明短期字符串会导致性能问题,则仅按照上述方式更改代码。
(我的直觉是每秒 400 个短期字符串应该不是问题,假设 1)它们不是很大并且 2)您选择了适合您的用例的 GC。)
| 归档时间: |
|
| 查看次数: |
122 次 |
| 最近记录: |