Skip to content

feat(memory): trace exporters — Perfetto/Chrome JSON, JFR events, android.os.Trace (SKEEP-003 P2, S1.5b) - #1073

Merged
michalharakal merged 1 commit into
developfrom
feature/1025-trace-exporters
Aug 23, 2026
Merged

michalharakal merged 1 commit into
developfrom
feature/1025-trace-exporters

Conversation

@michalharakal

Copy link
Copy Markdown
Contributor

Summary

SKEEP-003 slice S1.5b (milestone M1 #1002, PRD M1-F7 / M1-A7, decision #12): the event stream from #1061 gets its three consumers, so a decode loop can actually be looked at.

  • PerfettoTraceExporter (commonMain) — renders TraceEvents as the Chrome trace JSON that Perfetto and chrome://tracing read, with the mapping §4.9 asks for: one track per scope (allocations on a thread named after their ScopeKind, phases and kernels on the main thread), phases as B/E slices, kernel runs as complete slices labelled by op, kernel name and TensorIds, adapter insertions as instants carrying their byte cost (a silent dequantisation — the GGUF DEQUANTIZE_TO_FP32 over-allocates: 1.1B Q4_K_M needs >12 GB heap transiently (~4.4 GB legit) #782 class — becomes a mark on the timeline), live bytes per scope as counter tracks, and the memory plan as metadata. Timestamps convert ns → µs without a platform formatter.
  • JfrTraceSink (jvmMain) — the same events as JFR events under a SKaiNET category, so a memory trace opens in the IntelliJ profiler or JMC next to JIT, GC and allocation data. Recording stays JFR's business (-XX:StartFlightRecording, jcmd JFR.start); isEnabled mirrors whether JFR has the event types enabled, so emission is one boolean check when nothing is recording.
  • AndroidTraceSink (androidMain) — forwards to android.os.Trace so an on-device trace lines up with the OS view in Perfetto/systrace: phases and kernels as async sections, adapters / scope resets / allocations as counters, names truncated to the platform's 127-character limit, everything guarded by Trace.isEnabled().

Evidence (PerfettoTraceExporterTest, 11/11): a realistic decode step (plan → model allocation → decode phase → forward allocation → kernel run → adapter → scope reset → counter) renders with the right process/thread tracks, slice durations in µs, TensorId labels on the kernel span, the adapter's byte cost, and a live-bytes counter that drops back to zero at the scope reset — the visual signature M1-A7 describes. String escaping and ns→µs formatting are pinned.

Test plan

Full local gate (scripts/pr-gate.sh, JDK 25) — all legs passed; results in the first comment.

Closes #1025

🤖 Generated with Claude Code

…roid.os.Trace (SKEEP-003 P2)

Milestone M1 (#1002), PRD M1-F7 / M1-A7, decision #12. The event stream
from #1061 now has three consumers, so a decode loop can be *looked at*.

- PerfettoTraceExporter (commonMain): renders TraceEvents as the Chrome
  trace JSON that Perfetto and chrome://tracing read — one track per
  scope (allocations on a thread named after their ScopeKind, phases and
  kernels on the main thread), phases as B/E slices, kernel runs as
  complete slices labelled by op, kernel name and TensorIds, adapter
  insertions as instants carrying their byte cost (the #782 class becomes
  a visible mark), live bytes per scope as counter tracks — which is what
  makes a flat decode loop look flat — and the memory plan as metadata.
  Timestamps convert ns -> µs without a platform formatter.
- JfrTraceSink (jvmMain): the same events as JFR events under the SKaiNET
  category, so they open in the IntelliJ profiler or JMC next to JIT, GC
  and allocation data. Recording stays JFR's business
  (-XX:StartFlightRecording / jcmd JFR.start); isEnabled mirrors whether
  JFR has the event types enabled, so emission is a boolean check when it
  is not recording.
- AndroidTraceSink (androidMain): forwards to android.os.Trace so a
  SKaiNET trace lines up with the OS view in Perfetto/systrace on device:
  phases and kernels as async sections, adapters/scope resets/allocations
  as counters, names truncated to the 127-character limit, everything
  guarded by Trace.isEnabled().
- PerfettoTraceExporterTest: a realistic decode step renders with the
  right tracks, slices, durations, TensorId labels, adapter bytes and a
  live-bytes counter that drops to zero at the scope reset; string
  escaping and ns->µs formatting are pinned. 11/11.

Closes #1025

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@michalharakal

Copy link
Copy Markdown
Contributor Author

Local gate scripts/pr-gate.sh (JDK 25) on 8b6b2b2: all legs passed — jvmTest · apiCheck · JS/Wasm · linuxX64Test · assemble (incl. compileAndroidMain for the android.os.Trace sink) · Java consumer API tests.

Targeted: sk.ainet.lang.memory.trace.* 11/11.

@github-actions

Copy link
Copy Markdown

📖 Documentation Preview

The documentation has been built successfully for this PR.

Generated Files:

  • Operator documentation: docs/modules/operators/_generated_/
  • JSON schema output: operators.json

Artifacts:

  • Download the documentation-preview-1073 artifact to view the complete documentation locally.

This comment will be updated automatically when the PR is updated.

@michalharakal
michalharakal merged commit 1194d27 into develop Aug 23, 2026
15 checks passed
@michalharakal
michalharakal deleted the feature/1025-trace-exporters branch August 23, 2026 19:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[S1.5b] P2: trace exporters — Perfetto/Chrome JSON, JFR events (JVM), android.os.Trace (Android)

1 participant