Skip to content

Commit 725f287

Browse files
Add unified --profile flag with text and flamegraph output (#642)
## Summary - Replaces `--flamegraph <file>` with `--profile <file>` (text, default) or `--profile flamegraph:<file>` (folded stack format for flame graphs) - Ports the expression-level profiler from `universe/jsonnet/profiler`: measures self-time per evaluated expression via `Evaluator.visitExpr` instrumentation, with `System.nanoTime` overhead compensation - Text output shows top 50 expressions by self-time, plus aggregations by file name and expression type - Flamegraph output filters to Apply/ApplyBuiltin/comprehension frames, includes filenames for non-builtin calls - Deletes old `bench/ProfilingEvaluator` and `bench/RunProfiler`, superseded by the CLI-integrated profiler ## Test plan - [x] `sjsonnet.jvm[3.3.7].test` passes (140/140) - [x] `sjsonnet.jvm[2.13.18].compile` passes - [x] `sjsonnet.js[3.3.7].compile` passes - [x] Manual test: `--profile /tmp/out.txt` produces text profile - [x] Manual test: `--profile flamegraph:/tmp/out.txt` produces filtered folded stack output
1 parent 8d68091 commit 725f287

7 files changed

Lines changed: 420 additions & 391 deletions

File tree

bench/src/sjsonnet/bench/ProfilingEvaluator.scala

Lines changed: 0 additions & 197 deletions
This file was deleted.

bench/src/sjsonnet/bench/RunProfiler.scala

Lines changed: 0 additions & 88 deletions
This file was deleted.

sjsonnet/src-jvm-native/sjsonnet/Config.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ final case class Config(
168168
)
169169
maxStack: Int = 500,
170170
@arg(
171-
name = "flamegraph",
171+
name = "profile",
172172
doc =
173-
"Write a flame graph profile in folded stack format to the given file. Use with https://github.com/brendangregg/FlameGraph"
173+
"Profile evaluation and write results to a file. Format: --profile <file> or --profile <format>:<file> where format is 'text' (default) or 'flamegraph'"
174174
)
175-
flamegraph: Option[String] = None,
175+
profile: Option[String] = None,
176176
@arg(
177177
doc = "The jsonnet file you wish to evaluate",
178178
positional = true

sjsonnet/src-jvm-native/sjsonnet/SjsonnetMainBase.scala

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ object SjsonnetMainBase {
170170
warn,
171171
std,
172172
debugStats = debugStats,
173-
flamegraphFile = config.flamegraph
173+
profileOpt = config.profile
174174
)
175175
res <- {
176176
if (hasWarnings && config.fatalWarnings.value) Left("")
@@ -320,7 +320,7 @@ object SjsonnetMainBase {
320320
std: Val.Obj,
321321
evaluatorOverride: Option[Evaluator] = None,
322322
debugStats: DebugStats = null,
323-
flamegraphFile: Option[String] = None): Either[String, String] = {
323+
profileOpt: Option[String] = None): Either[String, String] = {
324324

325325
val (jsonnetCode, path) =
326326
if (config.exec.value) (file, wd / Util.wrapInLessThanGreaterThan("exec"))
@@ -349,8 +349,19 @@ object SjsonnetMainBase {
349349
wd
350350
)
351351

352+
val (profileFormat, profileFile) = profileOpt match {
353+
case Some(s) if s.startsWith("flamegraph:") =>
354+
(Some(ProfileOutputFormat.FlameGraph), Some(s.stripPrefix("flamegraph:")))
355+
case Some(s) if s.startsWith("text:") =>
356+
(Some(ProfileOutputFormat.Text), Some(s.stripPrefix("text:")))
357+
case Some(s) =>
358+
(Some(ProfileOutputFormat.Text), Some(s))
359+
case None =>
360+
(None, None)
361+
}
362+
352363
var currentPos: Position = null
353-
var profiler: FlameGraphProfiler = null
364+
var profilerInstance: Profiler = null
354365
val interp = new Interpreter(
355366
queryExtVar = (key: String) => extBinding.get(key).map(ExternalVariable.code),
356367
queryTlaVar = (key: String) => tlaBinding.get(key).map(ExternalVariable.code),
@@ -372,9 +383,9 @@ object SjsonnetMainBase {
372383
val ev = evaluatorOverride.getOrElse(
373384
super.createEvaluator(resolver, extVars, wd, settings)
374385
)
375-
if (flamegraphFile.isDefined) {
376-
profiler = new FlameGraphProfiler
377-
ev.flameGraphProfiler = profiler
386+
profileFormat.foreach { fmt =>
387+
profilerInstance = new Profiler(fmt, wd)
388+
ev.profiler = profilerInstance
378389
}
379390
ev
380391
}
@@ -448,8 +459,10 @@ object SjsonnetMainBase {
448459
case _ => renderNormal(config, interp, jsonnetCode, path, wd, () => currentPos)
449460
}
450461

451-
if (profiler != null)
452-
flamegraphFile.foreach(profiler.writeTo)
462+
if (profilerInstance != null)
463+
profileFile.foreach(f =>
464+
profilerInstance.writeTo(f, pos => interp.evaluator.prettyIndex(pos))
465+
)
453466

454467
result
455468
}

0 commit comments

Comments
 (0)