Skip to content

Commit

Permalink
Cache document parsing result
Browse files Browse the repository at this point in the history
  • Loading branch information
mervyn-mccreight committed Feb 5, 2025
1 parent 24e5951 commit cc80365
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 42 deletions.
6 changes: 6 additions & 0 deletions kgraphql/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ benchmark {
jmhVersion = "1.37"
}
}

configurations {
register("requestCachingBenchmark") {
include("com.apurebase.kgraphql.RequestCachingBenchmark")
}
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import java.util.concurrent.TimeUnit
@State(Scope.Benchmark)
@Warmup(iterations = 10)
@Measurement(iterations = 5)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@OutputTimeUnit(TimeUnit.SECONDS)
open class RequestCachingBenchmark {

@Param("true", "false")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package com.apurebase.kgraphql.function
import com.github.benmanes.caffeine.cache.Caffeine
import com.sksamuel.aedile.core.asLoadingCache
import kotlinx.coroutines.CoroutineScope
import kotlin.coroutines.EmptyCoroutineContext

fun <X : Any, Y : Any> (suspend (X) -> Y).memoized(scope: CoroutineScope = CoroutineScope(EmptyCoroutineContext), memorySize: Long): suspend (X) -> Y {
internal fun <X : Any, Y : Any> (suspend (X) -> Y).memoized(scope: CoroutineScope, memorySize: Long): suspend (X) -> Y {
val cache = Caffeine
.newBuilder()
.maximumSize(memorySize)
.asLoadingCache<X, Y>(scope) { this(it) }

return { cache.get(it) }
return cache::get
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import com.apurebase.kgraphql.schema.model.ast.TypeNode
import com.apurebase.kgraphql.schema.model.ast.ValueNode
import com.apurebase.kgraphql.schema.model.ast.VariableDefinitionNode

open class Parser {
internal class Parser {
private val options: Options
private val lexer: Lexer

Expand All @@ -56,11 +56,6 @@ open class Parser {

constructor(source: String, options: Options? = null) : this(Source(source), options)

constructor(lexer: Lexer, options: Options? = null) {
this.options = options ?: Options()
this.lexer = lexer
}

/**
* Converts a name lex token into a name parse node.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.apurebase.kgraphql.schema
import com.apurebase.kgraphql.Context
import com.apurebase.kgraphql.ValidationException
import com.apurebase.kgraphql.configuration.SchemaConfiguration
import com.apurebase.kgraphql.function.memoized
import com.apurebase.kgraphql.request.Introspection
import com.apurebase.kgraphql.request.Parser
import com.apurebase.kgraphql.request.VariablesJson
Expand All @@ -14,18 +15,21 @@ import com.apurebase.kgraphql.schema.execution.Executor.Parallel
import com.apurebase.kgraphql.schema.execution.ParallelRequestExecutor
import com.apurebase.kgraphql.schema.execution.RequestExecutor
import com.apurebase.kgraphql.schema.introspection.__Schema
import com.apurebase.kgraphql.schema.model.ast.DocumentNode
import com.apurebase.kgraphql.schema.model.ast.NameNode
import com.apurebase.kgraphql.schema.structure.LookupSchema
import com.apurebase.kgraphql.schema.structure.RequestInterpreter
import com.apurebase.kgraphql.schema.structure.SchemaModel
import com.apurebase.kgraphql.schema.structure.Type
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KClass

class DefaultSchema(
override val configuration: SchemaConfiguration,
internal val model: SchemaModel
) : Schema, __Schema by model, LookupSchema {
) : Schema, __Schema by model, LookupSchema, CoroutineScope {

companion object {
val OPERATION_NAME_PARAM = NameNode("operationName", null)
Expand All @@ -40,6 +44,16 @@ class DefaultSchema(

private val requestInterpreter: RequestInterpreter = RequestInterpreter(model)

private val parseRequest: (suspend (String) -> DocumentNode) =
if (configuration.useCachingDocumentParser) {
::parseDocument.memoized(
this,
configuration.documentParserCacheMaximumSize
)
} else {
::parseDocument
}

override suspend fun execute(
request: String,
variables: String?,
Expand All @@ -55,7 +69,7 @@ class DefaultSchema(
?.let { VariablesJson.Defined(configuration.objectMapper, variables) }
?: VariablesJson.Empty()

val document = Parser(request).parseDocument()
val document = parseRequest(request)

val executor = options.executor?.let(this@DefaultSchema::getExecutor) ?: defaultRequestExecutor

Expand All @@ -73,4 +87,9 @@ class DefaultSchema(
override fun inputTypeByKClass(kClass: KClass<*>): Type? = model.inputTypes[kClass]

override fun findTypeByName(name: String): Type? = model.allTypesByName[name]

@Suppress("RedundantSuspendModifier")
private suspend fun parseDocument(input: String): DocumentNode = Parser(input).parseDocument()

override val coroutineContext: CoroutineContext = configuration.coroutineDispatcher
}

0 comments on commit cc80365

Please sign in to comment.