Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary mapping of steps to queries #2020

Merged
merged 5 commits into from
Nov 25, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 24 additions & 23 deletions core/src/main/scala/caliban/execution/Executor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ object Executor {
val wrapPureValues = fieldWrappers.exists(_.wrapPureValues)
type ExecutionQuery[+A] = ZQuery[R, ExecutionError, A]

val execution = request.operationType match {
val execution = request.operationType match {
case OperationType.Query => queryExecution
case OperationType.Mutation => QueryExecution.Sequential
case OperationType.Subscription => QueryExecution.Sequential
}
def collectAll[E, A](as: List[ZQuery[R, E, A]]): ZQuery[R, E, List[A]] =
def collectAll[In, E, A](in: List[In])(as: In => ZQuery[R, E, A]): ZQuery[R, E, List[A]] =
execution match {
case QueryExecution.Sequential => ZQuery.collectAll(as)
case QueryExecution.Parallel => ZQuery.collectAllPar(as)
case QueryExecution.Batched => ZQuery.collectAllBatched(as)
case QueryExecution.Sequential => ZQuery.foreach(in)(as)
case QueryExecution.Parallel => ZQuery.foreachPar(in)(as)
case QueryExecution.Batched => ZQuery.foreachBatched(in)(as)
}

def reduceStep(
Expand Down Expand Up @@ -172,40 +172,41 @@ object Executor {
}

def makeObjectQuery(steps: List[(String, ReducedStep[R], FieldInfo)]) = {
var resolved: mutable.HashMap[String, ResponseValue] = null
def newMap() = new java.util.HashMap[String, ResponseValue](calculateMapCapacity(steps.size))

val queries =
if (wrapPureValues) steps.map((objectFieldQuery _).tupled)
var pures: java.util.HashMap[String, ResponseValue] = null
val _steps =
if (wrapPureValues) steps
else {
val queries = List.newBuilder[ExecutionQuery[(String, ResponseValue)]]
val queries = List.newBuilder[(String, ReducedStep[R], FieldInfo)]
var remaining = steps

while (!remaining.isEmpty) {
remaining.head match {
case (name, PureStep(value), _) =>
if (null == resolved) resolved = new mutable.HashMap[String, ResponseValue]()
resolved.update(name, value)
case (name, step, info) =>
queries += objectFieldQuery(name, step, info)
if (pures eq null) pures = newMap()
pures.putIfAbsent(name, value)
case step => queries += step
}
remaining = remaining.tail
}
queries.result()
}

if (null == resolved) collectAll(queries).map(ObjectValue.apply)
else
collectAll(queries).map { results =>
results.foreach(kv => resolved.update(kv._1, kv._2))
ObjectValue(steps.map { case (name, _, _) => name -> resolved(name) })
// Avoids placing of var into Function1 which will convert it to ObjectRef by the Scala compiler
val resolved = pures
collectAll(_steps)((objectFieldQuery _).tupled).map { results =>
if (resolved eq null) ObjectValue(results)
else {
results.foreach(kv => resolved.put(kv._1, kv._2))
ObjectValue(steps.map { case (name, _, _) => name -> resolved.get(name) })
}
}

}

def makeListQuery(steps: List[ReducedStep[R]], areItemsNullable: Boolean) =
collectAll(
if (areItemsNullable) steps.map(loop(_).catchAll(handleError))
else steps.map(loop)
).map(ListValue.apply)
collectAll(steps)(if (areItemsNullable) loop(_).catchAll(handleError) else loop)
.map(ListValue.apply)

def loop(step: ReducedStep[R]): ExecutionQuery[ResponseValue] =
step match {
Expand Down