Skip to content

Commit 595c19c

Browse files
committed
update benchmarks
1 parent 9cd31af commit 595c19c

File tree

3 files changed

+62
-36
lines changed

3 files changed

+62
-36
lines changed

README.md

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -119,29 +119,42 @@ These are benchmark tests of JsonPathLite against Jayway's JsonPath implementati
119119

120120
| Path Tested | JsonPathLite (ms) | JsonPath (ms) |
121121
| :---------- | :------ | :----- |
122-
| $[0]['tags'][3:] | 86 ms | 136 ms |
123-
| $[0]['tags'][0,3, 5] | 65 ms | 148 ms |
124-
| $..[:2] | 96 ms | 575 ms |
125-
| $..[2:] | 156 ms | 569 ms |
126-
| $..[1:-1] | 135 ms | 430 ms |
127-
| $[2]._id | 27 ms | 63 ms |
128-
| $[0]['tags'][3:5] | 66 ms | 115 ms |
129-
| $[0]['tags'][-3] | 45 ms | 100 ms |
130-
| $[0].friends[1].other.a.b['c'] | 70 ms | 164 ms |
131-
| $..name | 86 ms | 556 ms |
132-
| $..['email','name'] | 138 ms | 557 ms |
133-
| $..[1] | 86 ms | 467 ms |
134-
| $[0]['latitude','longitude', 'isActive'] | 70 ms | 138 ms |
135-
| $[0]['tags'][:3] | 64 ms | 120 ms |
122+
| $[0]['tags'][3:] | 67 ms *(34 ms w/ cache)* | 134 ms *(94 ms w/ cache)* |
123+
| $[0]['tags'][0,3,5] | 64 ms *(15 ms w/ cache)* | 140 ms *(65 ms w/ cache)* |
124+
| $..[:2] | 94 ms *(88 ms w/ cache)* | 581 ms *(564 ms w/ cache)* |
125+
| $..[2:] | 134 ms *(147 ms w/ cache)* | 568 ms *(537 ms w/ cache)* |
126+
| $..[1:-1] | 134 ms *(125 ms w/ cache)* | 445 ms *(433 ms w/ cache)* |
127+
| $[2]._id | 28 ms *(6 ms w/ cache)* | 64 ms *(36 ms w/ cache)* |
128+
| $[0]['tags'][3:5] | 67 ms *(18 ms w/ cache)* | 116 ms *(61 ms w/ cache)* |
129+
| $[0]['tags'][-3] | 46 ms *(5 ms w/ cache)* | 101 ms *(45 ms w/ cache)* |
130+
| $[0].friends[1].other.a.b['c'] | 70 ms *(10 ms w/ cache)* | 167 ms *(82 ms w/ cache)* |
131+
| $..name | 88 ms *(93 ms w/ cache)* | 566 ms *(624 ms w/ cache)* |
132+
| $..['email','name'] | 128 ms *(138 ms w/ cache)* | 570 ms *(564 ms w/ cache)* |
133+
| $..[1] | 84 ms *(89 ms w/ cache)* | 493 ms *(481 ms w/ cache)* |
134+
| $[0]['latitude','longitude','isActive'] | 68 ms *(13 ms w/ cache)* | 136 ms *(74 ms w/ cache)* |
135+
| $[0]['tags'][:3] | 66 ms *(19 ms w/ cache)* | 126 ms *(71 ms w/ cache)* |
136136

137137
**Compiling JsonPath string to internal tokens**
138138

139139
| Path size | JsonPathLite | JsonPath |
140140
| :-------- | :----------- | :------- |
141-
| 7 chars, 1 tokens | 9 ms | 10 ms |
142-
| 16 chars, 3 tokens | 25 ms | 32 ms |
143-
| 30 chars, 7 tokens | 50 ms | 72 ms |
144-
| 65 chars, 16 tokens | 120 ms | 172 ms |
145-
| 88 chars, 19 tokens | 159 ms | 232 ms |
141+
| 7 chars, 1 tokens | 10 ms *(2 ms w/ cache)* | 10 ms *(11 ms w/ cache)* |
142+
| 16 chars, 3 tokens | 25 ms *(2 ms w/ cache)* | 31 ms *(32 ms w/ cache)* |
143+
| 30 chars, 7 tokens | 50 ms *(1 ms w/ cache)* | 70 ms *(69 ms w/ cache)* |
144+
| 65 chars, 16 tokens | 118 ms *(1 ms w/ cache)* | 166 ms *(166 ms w/ cache)* |
145+
| 88 chars, 19 tokens | 154 ms *(1 ms w/ cache)* | 225 ms *(227 ms w/ cache)* |
146+
147+
# Cache
148+
JsonPathLite uses an LRU cache by default to cache compiled JsonPath tokens. If you don't want to use the cache, you can disable it or set the CacheProvider to use your own implementation of the Cache interface.
149+
```kotlin
150+
// Disable cache
151+
CacheProvider.setCache(null)
152+
153+
// Implement your own cache
154+
CacheProvider.setCache(object : Cache {
155+
override fun get(path: String): JsonPath? { ... }
156+
override fun put(path: String, jsonPath: JsonPath) { ... }
157+
)
158+
```
146159

147160
[![Analytics](https://ga-beacon.appspot.com/UA-116910991-3/jsonpathlite/index)](https://github.com/igrigorik/ga-beacon)

src/test/kotlin/com/nfeld/jsonpathlite/BaseTest.kt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,25 @@ open class BaseTest {
1515
companion object {
1616
// we need to reset this singleton across test suites
1717
fun resetCacheProvider() {
18-
println("Resetting CacheProvider singleton")
19-
2018
// use reflection to reset CacheProvider singleton to its initial state
2119
CacheProvider.javaClass.getDeclaredField("cache").apply {
2220
isAccessible = true
2321
set(null, null)
2422
}
2523
CacheProvider.javaClass.getDeclaredField("useDefault").apply {
2624
isAccessible = true
27-
set(null, true)
25+
setBoolean(null, true)
26+
}
27+
}
28+
29+
fun resetJaywayCacheProvider() {
30+
com.jayway.jsonpath.spi.cache.CacheProvider::class.java.getDeclaredField("cache").apply {
31+
isAccessible = true
32+
set(null, null)
33+
}
34+
com.jayway.jsonpath.spi.cache.CacheProvider::class.java.getDeclaredField("cachingEnabled").apply {
35+
isAccessible = true
36+
setBoolean(null, false)
2837
}
2938
}
3039

src/test/kotlin/com/nfeld/jsonpathlite/BenchmarkTest.kt

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package com.nfeld.jsonpathlite
22

33
import com.jayway.jsonpath.spi.cache.NOOPCache
44
import com.nfeld.jsonpathlite.cache.CacheProvider
5-
import com.nfeld.jsonpathlite.extension.read
65
import org.json.JSONArray
76
import org.junit.jupiter.api.BeforeAll
8-
import org.junit.jupiter.api.BeforeEach
97
import org.junit.jupiter.api.Test
108

119
class BenchmarkTest : BaseTest() {
@@ -22,12 +20,6 @@ class BenchmarkTest : BaseTest() {
2220

2321
printReadmeFormat = System.getProperty("readmeFormat")?.toBoolean() ?: false
2422
}
25-
26-
@JvmStatic
27-
@BeforeEach
28-
fun resetCache() {
29-
resetCacheProvider()
30-
}
3123
}
3224

3325
private val timestamp: Long
@@ -53,7 +45,7 @@ class BenchmarkTest : BaseTest() {
5345

5446
private fun benchmarkJsonPathLite(path: String, callsPerRun: Int = DEFAULT_CALLS_PER_RUN, runs: Int = DEFAULT_RUNS): Long {
5547
val jsonArray = JSONArray(LARGE_JSON) // pre-parse json
56-
return benchmark(callsPerRun, runs) { jsonArray.read<String>(path) }
48+
return benchmark(callsPerRun, runs) { JsonPath(path).readFromJson<String>(jsonArray) }
5749
}
5850

5951
private fun benchmarkJsonPath(path: String, callsPerRun: Int = DEFAULT_CALLS_PER_RUN, runs: Int = DEFAULT_RUNS): Long {
@@ -62,23 +54,32 @@ class BenchmarkTest : BaseTest() {
6254
}
6355

6456
private fun runBenchmarksAndPrintResults(path: String, callsPerRun: Int = DEFAULT_CALLS_PER_RUN, runs: Int = DEFAULT_RUNS) {
57+
// reset caches to initial position, default on
58+
resetCaches()
59+
6560
// first benchmarks will be using caches
6661
val lite = benchmarkJsonPathLite(path, callsPerRun, runs)
6762
val other = benchmarkJsonPath(path, callsPerRun, runs)
6863

6964
// now disable caches
7065
CacheProvider.setCache(null)
66+
resetJaywayCacheProvider()
7167
com.jayway.jsonpath.spi.cache.CacheProvider.setCache(NOOPCache())
7268
val liteNoCache = benchmarkJsonPathLite(path, callsPerRun, runs)
7369
val otherNoCache = benchmarkJsonPath(path, callsPerRun, runs)
7470

7571
if (printReadmeFormat) {
76-
println("| $path | ${lite} ms | ${other} ms | $liteNoCache ms | $otherNoCache ms |")
72+
println("| $path | $liteNoCache ms *($lite ms w/ cache)* | $otherNoCache ms *($other ms w/ cache)* |")
7773
} else {
78-
println("$path lite: ${lite}, jsonpath: ${other} Without caches: lite: ${liteNoCache}, jsonpath: ${otherNoCache}")
74+
println("$path lite: ${lite}, jsonpath: ${other} Without caches: lite: ${liteNoCache}, jsonpath: ${otherNoCache}")
7975
}
8076
}
8177

78+
private fun resetCaches() {
79+
resetCacheProvider()
80+
resetJaywayCacheProvider()
81+
}
82+
8283
@Test
8384
fun benchmarkDeepPath() {
8485
runBenchmarksAndPrintResults("$[0].friends[1].other.a.b['c']")
@@ -93,23 +94,27 @@ class BenchmarkTest : BaseTest() {
9394
fun benchmarkPathCompile() {
9495

9596
fun compile(path: String) {
97+
resetCaches()
98+
9699
// first with caches
97100
val lite = benchmark { JsonPath(path) }
98101
val other = benchmark { com.jayway.jsonpath.JsonPath.compile(path) }
99102

100103
// now disable caches
101104
CacheProvider.setCache(null)
105+
resetJaywayCacheProvider()
102106
com.jayway.jsonpath.spi.cache.CacheProvider.setCache(NOOPCache())
107+
103108
val liteNoCache = benchmark { JsonPath(path) }
104109
val otherNoCache = benchmark { com.jayway.jsonpath.JsonPath.compile(path) }
105110

106111
val numTokens = PathCompiler.compile(path).size
107112
val name = "${path.length} chars, $numTokens tokens"
108113

109114
if (printReadmeFormat) {
110-
println("| $name | ${lite} ms | ${other} ms | $liteNoCache ms | $otherNoCache ms |")
115+
println("| $name | $liteNoCache ms *($lite ms w/ cache)* | $otherNoCache ms *($other ms w/ cache)* |")
111116
} else {
112-
println("$name lite: ${lite}, jsonpath: ${other} Without caches: lite: ${liteNoCache}, jsonpath: ${otherNoCache}")
117+
println("$name lite: ${lite}, jsonpath: ${other} Without caches: lite: ${liteNoCache}, jsonpath: ${otherNoCache}")
113118
}
114119
}
115120

@@ -124,7 +129,6 @@ class BenchmarkTest : BaseTest() {
124129
fun benchmarkDeepScans() {
125130
val callsPerRun = 20000
126131
val runs = 10
127-
runBenchmarksAndPrintResults("$..tags", callsPerRun, runs)
128132
runBenchmarksAndPrintResults("$..name", callsPerRun, runs)
129133
runBenchmarksAndPrintResults("$..['email','name']", callsPerRun, runs)
130134
runBenchmarksAndPrintResults("$..[1]", callsPerRun, runs)

0 commit comments

Comments
 (0)