Skip to content

Commit

Permalink
JPERF-1401: Reuse JsonProvider
Browse files Browse the repository at this point in the history
Avoid scanning the classpath on every JSON value creation.

Repeat the same perf fix as in atlassian/report#97
I apologize for not adding a test for the APIs in this lib.
Our team is running out of time.
Dear future reader, if the libs get development time again, I would:
* import a big action metrics file with lots of drilldown JSONs
* run parsing and serialization in parallel with concurrency = 4
  • Loading branch information
dagguh committed Oct 27, 2023
1 parent e2ff9de commit 9da6373
Show file tree
Hide file tree
Showing 13 changed files with 44 additions and 30 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Dropping a requirement of a major version of a dependency is a new contract.
## [Unreleased]
[Unreleased]: https://github.com/atlassian/jira-actions/compare/release-3.24.0...master

### Fixed
- Speed up all JSON code, by reusing a `JsonProvider` instance. Fix the same root cause as in [JPERF-1401].

[JPERF-1401]: https://ecosystem.atlassian.net/browse/JPERF-1401

## [3.24.0] - 2023-10-24
[3.24.0]: https://github.com/atlassian/jira-actions/compare/release-3.23.1...release-3.24.0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.atlassian.performance.tools.jiraactions

import javax.json.spi.JsonProvider

internal object JsonProviderSingleton {

val JSON: JsonProvider = JsonProvider.provider()
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.atlassian.performance.tools.jiraactions.api

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.w3c.RecordedPerformanceEntries
import com.atlassian.performance.tools.jiraactions.w3c.VerboseJsonFormat
import java.time.Duration
import java.time.Instant
import java.util.*
import javax.json.Json
import javax.json.JsonObject

/**
Expand Down Expand Up @@ -63,7 +63,7 @@ data class ActionMetric @Deprecated("Use ActionMetric.Builder instead.") constru

@Deprecated("Use AppendableActionMetricOutput instead.")
fun toJson(): JsonObject {
val builder = Json.createObjectBuilder()
val builder = JSON.createObjectBuilder()
.add("label", label)
.add("result", result.name)
.add("duration", duration.toString())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.atlassian.performance.tools.jiraactions.api.action

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.ActionType
import com.atlassian.performance.tools.jiraactions.api.SEARCH_WITH_JQL
import com.atlassian.performance.tools.jiraactions.api.SeededRandom
Expand All @@ -15,7 +16,6 @@ import com.atlassian.performance.tools.jiraactions.api.page.issuenav.DetailView
import com.atlassian.performance.tools.jiraactions.api.page.issuenav.IssueNavResultsView
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import javax.json.Json
import javax.json.JsonObject

class SearchIssues private constructor(
Expand Down Expand Up @@ -109,7 +109,7 @@ class SearchIssues private constructor(
json.getBoolean("switched")
)

fun serialize(): JsonObject = Json.createObjectBuilder()
fun serialize(): JsonObject = JSON.createObjectBuilder()
.add("desiredView", desiredView)
.add("selectedBefore", selectedBefore)
.add("selectedAfter", selectedAfter)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.atlassian.performance.tools.jiraactions.api.action

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.VIEW_COMMENT
import com.atlassian.performance.tools.jiraactions.api.WebJira
import com.atlassian.performance.tools.jiraactions.api.measure.ActionMeter
import com.atlassian.performance.tools.jiraactions.api.memories.CommentMemory
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import javax.json.Json

class ViewCommentAction(
private val jira: WebJira,
Expand All @@ -26,7 +26,7 @@ class ViewCommentAction(
key = VIEW_COMMENT,
action = { jira.goToComment(comment.url).validateCommentIsFocused(comment.id) },
observation = { page ->
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("issueKey", page.getIssueKey())
.add("commentId", comment.id)
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.atlassian.performance.tools.jiraactions.api.action

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.VIEW_ISSUE
import com.atlassian.performance.tools.jiraactions.api.WebJira
import com.atlassian.performance.tools.jiraactions.api.measure.ActionMeter
import com.atlassian.performance.tools.jiraactions.api.memories.*
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import javax.json.Json

class ViewIssueAction private constructor(
private val jira: WebJira,
Expand Down Expand Up @@ -44,7 +44,7 @@ class ViewIssueAction private constructor(
key = VIEW_ISSUE,
action = { jira.goToIssue(issueKey).waitForSummary() },
observation = { page ->
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("issueKey", issueKey)
.add("issueId", page.getIssueId())
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.atlassian.performance.tools.jiraactions.api.format

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.ActionMetric
import com.atlassian.performance.tools.jiraactions.api.ActionResult
import java.time.Duration
import java.time.Instant
import java.util.*
import javax.json.Json
import javax.json.JsonObject

/**
Expand All @@ -16,7 +16,7 @@ class MetricCompactJsonFormat: MetricJsonFormat {
override fun serialize(
actionMetric: ActionMetric
): JsonObject = actionMetric.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("label", label)
.add("result", result.name)
.add("duration", duration.toString())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.atlassian.performance.tools.jiraactions.api.format

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.ActionMetric
import com.atlassian.performance.tools.jiraactions.api.ActionResult
import com.atlassian.performance.tools.jiraactions.w3c.VerboseJsonFormat
import java.time.Duration
import java.time.Instant
import java.util.*
import javax.json.Json
import javax.json.JsonObject

class MetricVerboseJsonFormat : MetricJsonFormat {
Expand All @@ -16,7 +16,7 @@ class MetricVerboseJsonFormat : MetricJsonFormat {
override fun serialize(
actionMetric: ActionMetric
): JsonObject = actionMetric.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("label", label)
.add("result", result.name)
.add("duration", duration.toString())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.atlassian.performance.tools.jiraactions.api.observation

import javax.json.Json
import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import javax.json.JsonObject

data class IssueObservation(
val issueKey: String
) {
constructor(json: JsonObject) : this(json.getString("issueKey"))

fun serialize(): JsonObject = Json.createObjectBuilder()
fun serialize(): JsonObject = JSON.createObjectBuilder()
.add("issueKey", issueKey)
.build()
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.atlassian.performance.tools.jiraactions.api.observation

import javax.json.Json
import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import javax.json.JsonObject

data class IssuesOnBoard(val issues: Int) {
constructor(json: JsonObject) : this(json.getInt("issues"))

fun serialize(): JsonObject = Json.createObjectBuilder().add("issues", issues).build()
}
fun serialize(): JsonObject = JSON.createObjectBuilder().add("issues", issues).build()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.atlassian.performance.tools.jiraactions.api.observation

import javax.json.Json
import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import javax.json.JsonObject

data class SearchJqlObservation(
Expand All @@ -10,9 +10,9 @@ data class SearchJqlObservation(
) {
constructor(json: JsonObject) : this(json.getString("jql"), json.getInt("issues"), json.getInt("totalResults"))

fun serialize(): JsonObject = Json.createObjectBuilder()
fun serialize(): JsonObject = JSON.createObjectBuilder()
.add("jql", jql)
.add("issues", issues)
.add("totalResults", totalResults)
.build()
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.atlassian.performance.tools.jiraactions.api.parser

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.ActionMetric
import com.atlassian.performance.tools.jiraactions.api.format.MetricJsonFormat
import com.atlassian.performance.tools.jiraactions.api.format.MetricVerboseJsonFormat
import org.apache.logging.log4j.LogManager
import java.io.InputStream
import java.io.StringReader
import java.util.stream.Stream
import javax.json.Json
import javax.json.JsonStructure
import kotlin.streams.asStream
import kotlin.streams.toList
Expand Down Expand Up @@ -35,7 +35,7 @@ class ActionMetricsParser(private val format: MetricJsonFormat) {
private fun parseOrNull(
line: String
): JsonStructure? = try {
Json.createReader(StringReader(line)).read()
JSON.createReader(StringReader(line)).read()
} catch (e: Exception) {
logger.debug("Discarding '$line'", e)
null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.atlassian.performance.tools.jiraactions.w3c

import com.atlassian.performance.tools.jiraactions.JsonProviderSingleton.JSON
import com.atlassian.performance.tools.jiraactions.api.w3c.*
import java.time.Duration
import javax.json.Json
Expand All @@ -11,7 +12,7 @@ internal class VerboseJsonFormat {
fun serializeRecordedEntries(
entries: RecordedPerformanceEntries
): JsonObject = entries.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("navigations", navigations.map { serializeNavigationTiming(it) }.toJsonArray())
.add("resources", resources.map { serializeResourceTiming(it) }.toJsonArray())
.add("elements", (elements.map { serializeElementTiming(it) }).toJsonArray())
Expand All @@ -38,7 +39,7 @@ internal class VerboseJsonFormat {
private fun serializeEntry(
entry: PerformanceEntry
): JsonObject = entry.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("name", name)
.add("entryType", entryType)
.add("startTime", startTime.toString())
Expand All @@ -60,7 +61,7 @@ internal class VerboseJsonFormat {
private fun serializeResourceTiming(
resourceTiming: PerformanceResourceTiming
): JsonObject = resourceTiming.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("entry", serializeEntry(entry))
.add("initiatorType", initiatorType)
.add("nextHopProtocol", nextHopProtocol)
Expand Down Expand Up @@ -118,7 +119,7 @@ internal class VerboseJsonFormat {
private fun serializeNavigationTiming(
navigationTiming: PerformanceNavigationTiming
): JsonObject = navigationTiming.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("resource", serializeResourceTiming(resource))
.add("unloadEventStart", unloadEventStart.toString())
.add("unloadEventEnd", unloadEventEnd.toString())
Expand Down Expand Up @@ -154,7 +155,7 @@ internal class VerboseJsonFormat {
private fun serializeServerTiming(
serverTiming: PerformanceServerTiming
): JsonObject = serverTiming.run {
Json.createObjectBuilder()
JSON.createObjectBuilder()
.add("name", serverTiming.name)
.add("duration", serverTiming.duration.toString())
.add("description", serverTiming.description)
Expand All @@ -172,7 +173,7 @@ internal class VerboseJsonFormat {
}

private fun List<JsonObject>.toJsonArray(): JsonArray {
val builder = Json.createArrayBuilder()
val builder = JSON.createArrayBuilder()
forEach { builder.add(it) }
return builder.build()
}
Expand All @@ -184,7 +185,7 @@ internal class VerboseJsonFormat {
private fun serializeElementTiming(
elementTiming: PerformanceElementTiming
): JsonObject = elementTiming.run {
return Json.createObjectBuilder()
return JSON.createObjectBuilder()
.add("renderTime", renderTime.toString())
.add("loadTime", loadTime.toString())
.add("identifier", identifier)
Expand Down

0 comments on commit 9da6373

Please sign in to comment.