From e99a6ee33e587a4651dc1d328d4759d6503d421f Mon Sep 17 00:00:00 2001 From: Gregor Lohaus Date: Sun, 31 May 2026 21:18:07 +0200 Subject: [PATCH] split snapshot profiler bucket into update vs marshal The snapshot bucket lumped ghostty's native dirty-state update together with the Java-side cell marshaling. Time them separately to see which half of the ~7ms/frame snapshot cost (now the dominant frame cost after the detectShift hoist) is the real target. Co-Authored-By: Claude Opus 4.8 --- src/main/java/com/gregor/jprototerm/RenderProfiler.java | 7 +++++-- src/main/java/com/gregor/jprototerm/TerminalPane.java | 8 ++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/gregor/jprototerm/RenderProfiler.java b/src/main/java/com/gregor/jprototerm/RenderProfiler.java index 28e5f64..a8cf863 100644 --- a/src/main/java/com/gregor/jprototerm/RenderProfiler.java +++ b/src/main/java/com/gregor/jprototerm/RenderProfiler.java @@ -18,8 +18,11 @@ final class RenderProfiler { static final int FINGERPRINT = 1; static final int DRAW = 2; static final int FRAME = 3; - private static final int BUCKETS = 4; - private static final String[] NAMES = {"snapshot", "fingerprint", "draw", "frame-total"}; + static final int UPDATE = 4; + static final int MARSHAL = 5; + private static final int BUCKETS = 6; + private static final String[] NAMES = + {"snapshot", "fingerprint", "draw", "frame-total", "update", "marshal"}; private static final boolean ENABLED = Boolean.getBoolean("jprototerm.profile") || "1".equals(System.getenv("JPROTOTERM_PROFILE")); diff --git a/src/main/java/com/gregor/jprototerm/TerminalPane.java b/src/main/java/com/gregor/jprototerm/TerminalPane.java index ac3318e..5f364bd 100644 --- a/src/main/java/com/gregor/jprototerm/TerminalPane.java +++ b/src/main/java/com/gregor/jprototerm/TerminalPane.java @@ -160,13 +160,21 @@ public final class TerminalPane implements AutoCloseable { synchronized (terminal) { long version = contentVersion.get(); if (full) { + long updateStart = RenderProfiler.start(); renderState.update(terminal); + RenderProfiler.stop(RenderProfiler.UPDATE, updateStart); + long marshalStart = RenderProfiler.start(); cachedSnapshot = renderState.snapshot(); + RenderProfiler.stop(RenderProfiler.MARSHAL, marshalStart); renderState.resetDirty(); snapshotVersion = version; } else if (snapshotVersion != version) { + long updateStart = RenderProfiler.start(); renderState.update(terminal); + RenderProfiler.stop(RenderProfiler.UPDATE, updateStart); + long marshalStart = RenderProfiler.start(); cachedSnapshot = renderState.snapshotIncremental(); + RenderProfiler.stop(RenderProfiler.MARSHAL, marshalStart); renderState.resetDirty(); snapshotVersion = version; }