Skip to content

Commit 680b1a8

Browse files
authored
Fix performance regression in split by avoiding allocating substring per char (#237)
This PR fixes a performance regression from #227 / 4c85bde which I overlooked in review: When generalizing the optimized non-Pattern-based split code, that commit introduced a `.substring()` on each character, producing tons of garbage. Instead, I think we can do a `.startsWith(splitPattern, i)`: this should be much faster because it will avoid unnecessary garbage string creation (plus I'm pretty sure that `startsWith` is optimized in modern JDKs). I also removed the use of `breakable` and replaced it with an update to the `while` condition.
1 parent f5bf391 commit 680b1a8

1 file changed

Lines changed: 9 additions & 12 deletions

File tree

sjsonnet/src/sjsonnet/Std.scala

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import sjsonnet.Expr.Member.Visibility
99

1010
import scala.collection.Searching._
1111
import scala.collection.mutable
12-
import scala.util.control.Breaks.{break, breakable}
1312
import scala.util.matching.Regex
1413

1514
/**
@@ -642,17 +641,15 @@ class Std {
642641
var sz = 0
643642
var i = 0
644643
var start = 0
645-
breakable {
646-
while (i < str.length) {
647-
if (maxSplits >= 0 && sz >= maxSplits) {
648-
break
649-
}
650-
if (str.slice(i, i + cStr.length) == cStr) {
651-
val finalStr = Val.Str(pos, str.slice(start, i))
652-
b.+=(finalStr)
653-
start = i + cStr.length
654-
sz += 1
655-
}
644+
645+
while (i <= str.length - cStr.length && (maxSplits < 0 || sz < maxSplits)) {
646+
if (str.startsWith(cStr, i)) {
647+
val finalStr = Val.Str(pos, str.substring(start, i))
648+
b.+=(finalStr)
649+
start = i + cStr.length
650+
sz += 1
651+
i += cStr.length
652+
} else {
656653
i += 1
657654
}
658655
}

0 commit comments

Comments
 (0)