Skip to content

Commit 45d28ee

Browse files
committed
perf: mitigate *embarrassing* performance difference with java-diff
testPerformanceProblemsIssue124 showed a 30s vs 7s runtime. Moving to fields instead of getters drastically improved performance down to 10s. Still, not optimal.
1 parent 00544ec commit 45d28ee

File tree

8 files changed

+53
-31
lines changed

8 files changed

+53
-31
lines changed

build.gradle.kts

+4-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ kotlin {
3636
jvmTarget = JvmTarget.JVM_1_8
3737

3838
// Output interfaces with default methods
39-
freeCompilerArgs.add("-Xjvm-default=all")
39+
freeCompilerArgs.addAll(
40+
"-Xjvm-default=all", // Output interfaces with default methods
41+
"-Xno-param-assertions", // Remove Intrinsics.checkNotNullParameter
42+
)
4043
}
4144
}
4245

src/commonMain/kotlin/io/github/petertrr/diffutils/algorithm/Change.kt

+6-5
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
package io.github.petertrr.diffutils.algorithm
2020

2121
import io.github.petertrr.diffutils.patch.DeltaType
22+
import kotlin.jvm.JvmField
2223

2324
public data class Change(
24-
val deltaType: DeltaType,
25-
val startOriginal: Int,
26-
val endOriginal: Int,
27-
val startRevised: Int,
28-
val endRevised: Int,
25+
@JvmField val deltaType: DeltaType,
26+
@JvmField val startOriginal: Int,
27+
@JvmField val endOriginal: Int,
28+
@JvmField val startRevised: Int,
29+
@JvmField val endRevised: Int,
2930
)

src/commonMain/kotlin/io/github/petertrr/diffutils/algorithm/myers/MyersDiffWithLinearSpace.kt

+13-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import io.github.petertrr.diffutils.algorithm.DiffAlgorithmListener
2424
import io.github.petertrr.diffutils.algorithm.DiffEqualizer
2525
import io.github.petertrr.diffutils.algorithm.EqualsDiffEqualizer
2626
import io.github.petertrr.diffutils.patch.DeltaType
27+
import kotlin.jvm.JvmField
2728

2829
public class MyersDiffWithLinearSpace<T>(
2930
private val equalizer: DiffEqualizer<T> = EqualsDiffEqualizer(),
@@ -202,18 +203,25 @@ public class MyersDiffWithLinearSpace<T>(
202203
}
203204

204205
private class DiffData<T>(
205-
val source: List<T>,
206-
val target: List<T>,
206+
@JvmField val source: List<T>,
207+
@JvmField val target: List<T>,
207208
) {
209+
@JvmField
208210
val size = source.size + target.size + 2
211+
212+
@JvmField
209213
val vDown = IntArray(size)
214+
215+
@JvmField
210216
val vUp = IntArray(size)
217+
218+
@JvmField
211219
val script = ArrayList<Change>()
212220
}
213221

214222
private class Snake(
215-
val start: Int,
216-
val end: Int,
217-
val diag: Int,
223+
@JvmField val start: Int,
224+
@JvmField val end: Int,
225+
@JvmField val diag: Int,
218226
)
219227
}

src/commonMain/kotlin/io/github/petertrr/diffutils/algorithm/myers/PathNode.kt

+8-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package io.github.petertrr.diffutils.algorithm.myers
2020

21+
import kotlin.jvm.JvmField
22+
2123
/**
2224
* A node in a diffpath.
2325
*
@@ -29,20 +31,17 @@ package io.github.petertrr.diffutils.algorithm.myers
2931
* @param prev The previous node in the path, if any
3032
*/
3133
internal class PathNode(
32-
val i: Int,
33-
val j: Int,
34-
val snake: Boolean,
35-
val bootstrap: Boolean,
34+
@JvmField val i: Int,
35+
@JvmField val j: Int,
36+
@JvmField val snake: Boolean,
37+
@JvmField val bootstrap: Boolean,
3638
prev: PathNode? = null,
3739
) {
3840
/**
3941
* The previous node in the path.
4042
*/
41-
val prev: PathNode? = if (snake) {
42-
prev
43-
} else {
44-
prev?.previousSnake()
45-
}
43+
@JvmField
44+
val prev: PathNode? = if (snake) prev else prev?.previousSnake()
4645

4746
/**
4847
* Skips sequences of [PathNodes][PathNode] until a snake or bootstrap node is found, or the end of the

src/commonMain/kotlin/io/github/petertrr/diffutils/patch/Chunk.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package io.github.petertrr.diffutils.patch
2020

21+
import kotlin.jvm.JvmField
22+
2123
/**
2224
* Holds the information about the part of text involved in the diff process.
2325
*
@@ -31,9 +33,9 @@ package io.github.petertrr.diffutils.patch
3133
* @param T The type of the compared elements in the 'lines'
3234
*/
3335
public data class Chunk<T>(
34-
val position: Int,
35-
val lines: List<T>,
36-
val changePosition: List<Int>? = null,
36+
@JvmField val position: Int,
37+
@JvmField val lines: List<T>,
38+
@JvmField val changePosition: List<Int>? = null,
3739
) {
3840
/**
3941
* Verifies that this chunk's saved text matches the corresponding text in the given sequence.

src/commonMain/kotlin/io/github/petertrr/diffutils/patch/Patch.kt

+8-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
package io.github.petertrr.diffutils.patch
2020

2121
import io.github.petertrr.diffutils.algorithm.Change
22+
import kotlin.jvm.JvmOverloads
23+
import kotlin.jvm.JvmStatic
2224

2325
/**
2426
* Describes the patch holding all deltas between the original and revised texts.
@@ -87,17 +89,13 @@ public class Patch<T>(private var conflictOutput: ConflictOutput<T> = ExceptionP
8789
}
8890

8991
public companion object {
90-
public fun <T> generate(original: List<T>, revised: List<T>, changes: List<Change>): Patch<T> =
91-
generate(original, revised, changes, false)
92-
93-
private fun <T> buildChunk(start: Int, end: Int, data: List<T>): Chunk<T> =
94-
Chunk(start, data.slice(start..<end))
95-
92+
@JvmStatic
93+
@JvmOverloads
9694
public fun <T> generate(
9795
original: List<T>,
9896
revised: List<T>,
9997
changes: List<Change>,
100-
includeEquals: Boolean,
98+
includeEquals: Boolean = false,
10199
): Patch<T> {
102100
val patch = Patch<T>()
103101
var startOriginal = 0
@@ -144,5 +142,8 @@ public class Patch<T>(private var conflictOutput: ConflictOutput<T> = ExceptionP
144142

145143
return patch
146144
}
145+
146+
private fun <T> buildChunk(start: Int, end: Int, data: List<T>): Chunk<T> =
147+
Chunk(start, data.slice(start..<end))
147148
}
148149
}

src/commonMain/kotlin/io/github/petertrr/diffutils/text/DiffRow.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,16 @@
1818
*/
1919
package io.github.petertrr.diffutils.text
2020

21+
import kotlin.jvm.JvmField
22+
2123
/**
2224
* Describes the diff row in form `[tag, oldLine, newLine]` for showing the difference between two texts.
2325
*/
24-
public data class DiffRow(val tag: Tag, val oldLine: String, val newLine: String) {
26+
public data class DiffRow(
27+
@JvmField val tag: Tag,
28+
@JvmField val oldLine: String,
29+
@JvmField val newLine: String,
30+
) {
2531
public enum class Tag {
2632
INSERT,
2733
DELETE,

src/commonTest/kotlin/io/github/petertrr/diffutils/algorithm/myers/MyersDiffWithLinearSpaceTest.kt

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package io.github.petertrr.diffutils.algorithm.myers
2121
import io.github.petertrr.diffutils.algorithm.DiffAlgorithmListener
2222
import io.github.petertrr.diffutils.diff
2323
import io.github.petertrr.diffutils.patch.Patch
24+
import kotlin.test.Ignore
2425
import kotlin.test.Test
2526
import kotlin.test.assertEquals
2627
import kotlin.time.measureTimedValue
@@ -91,6 +92,7 @@ class MyersDiffWithLinearSpaceTest {
9192
}
9293

9394
@Test
95+
@Ignore
9496
fun testPerformanceProblemsIssue124() {
9597
val old = listOf("abcd")
9698
val new = (0..<90000)

0 commit comments

Comments
 (0)