From 1df8c23e6b2af3c178c14c9c0a52ed7832db1cd9 Mon Sep 17 00:00:00 2001 From: Brian Harrington Date: Tue, 15 Oct 2024 13:37:56 -0500 Subject: [PATCH] eval: precompute expression string for large group by expressions it can be expensive to recompute the expression string for every output message. Precompute for all messages from a given expression. --- .../com/netflix/atlas/eval/model/TimeSeriesMessage.scala | 8 ++++++-- .../com/netflix/atlas/eval/stream/FinalExprEval.scala | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/atlas-eval/src/main/scala/com/netflix/atlas/eval/model/TimeSeriesMessage.scala b/atlas-eval/src/main/scala/com/netflix/atlas/eval/model/TimeSeriesMessage.scala index fa36f9b9d..dfc31f23f 100644 --- a/atlas-eval/src/main/scala/com/netflix/atlas/eval/model/TimeSeriesMessage.scala +++ b/atlas-eval/src/main/scala/com/netflix/atlas/eval/model/TimeSeriesMessage.scala @@ -124,14 +124,18 @@ object TimeSeriesMessage { * Time series to use for the message. * @param palette * If defined then include presentation metadata. + * @param exprStr + * String view of the expression. Should match `expr`, but may be precomputed for + * group by expressions with many messages. */ def apply( expr: StyleExpr, context: EvalContext, ts: TimeSeries, - palette: Option[String] = None + palette: Option[String] = None, + exprStr: Option[String] = None ): TimeSeriesMessage = { - val query = expr.toString + val query = exprStr.getOrElse(expr.toString) val offset = Strings.toString(Duration.ofMillis(expr.offset)) val outputTags = ts.tags + (TagKey.offset -> offset) val id = TaggedItem.computeId(outputTags + ("atlas.query" -> query)).toString diff --git a/atlas-eval/src/main/scala/com/netflix/atlas/eval/stream/FinalExprEval.scala b/atlas-eval/src/main/scala/com/netflix/atlas/eval/stream/FinalExprEval.scala index f47d1bdb1..8a242ff21 100644 --- a/atlas-eval/src/main/scala/com/netflix/atlas/eval/stream/FinalExprEval.scala +++ b/atlas-eval/src/main/scala/com/netflix/atlas/eval/stream/FinalExprEval.scala @@ -201,6 +201,7 @@ private[stream] class FinalExprEval(exprInterpreter: ExprInterpreter) // Generate the time series and diagnostic output val output = recipients.flatMap { case (styleExpr, infos) => + val exprStr = styleExpr.toString val ids = infos.map(_.id) // Use an identity map for the state to ensure that multiple equivalent stateful // expressions, e.g. derivative(a) + derivative(a), will have isolated state. @@ -221,7 +222,8 @@ private[stream] class FinalExprEval(exprInterpreter: ExprInterpreter) styleExpr, context, t.withLabel(styleExpr.legend(t)), - info.palette + info.palette, + Some(exprStr) ) new MessageEnvelope(info.id, ts) }