Skip to content

Commit b8b0f87

Browse files
committed
Speed up line/column in OffsetPosition
Building the index again and again for every OffsetPosition instance makes very little sense. So this makes it build it only once for a given source. I'm not sure if this is the best way to implement it and I'm afraid that a global synchronized map may be a performance bottleneck once the number of processors goes into the hundreds, but I know very little Scala/Java to do this properly. :-( Fixes http://stackoverflow.com/questions/14707127/accessing-position-information-in-a-scala-combinatorparser-kills-performance
1 parent aacfcf8 commit b8b0f87

File tree

1 file changed

+19
-0
lines changed

1 file changed

+19
-0
lines changed

src/main/scala/scala/util/parsing/input/OffsetPosition.scala

+19
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ case class OffsetPosition(source: java.lang.CharSequence, offset: Int) extends P
2323

2424
/** An index that contains all line starts, including first line, and eof. */
2525
private lazy val index: Array[Int] = {
26+
Option(OffsetPosition.indexCache.get(source)) match {
27+
case Some(index) => index
28+
case None =>
29+
val index = genIndex
30+
OffsetPosition.indexCache.put(source, index)
31+
index
32+
}
33+
}
34+
35+
private def genIndex: Array[Int] = {
2636
val lineStarts = new ArrayBuffer[Int]
2737
lineStarts += 0
2838
for (i <- 0 until source.length)
@@ -71,3 +81,12 @@ case class OffsetPosition(source: java.lang.CharSequence, offset: Int) extends P
7181
this.line == that.line && this.column < that.column
7282
}
7383
}
84+
85+
/** An object holding the index cache.
86+
*
87+
* @author Tomáš Janoušek
88+
*/
89+
object OffsetPosition {
90+
private lazy val indexCache = java.util.Collections.synchronizedMap(
91+
new java.util.WeakHashMap[java.lang.CharSequence, Array[Int]])
92+
}

0 commit comments

Comments
 (0)