Package limn.demo

Class PerfFooter

java.lang.Object
limn.scene.Widget
limn.demo.PerfFooter

public final class PerfFooter extends Widget
Performance footer: two rows of live gauges, what a frame costs (FPS, CPU frame time, GPU time, widgets painted, repaint regions) over what the process costs (CPU, heap, GC pause, 3D memory, 3D draw calls), each with the current value and a per-second bar chart of the last 60 ticks (the oldest tick falls off once the window is full). Everything is drawn with the Limn Canvas.

Painted and Regions are the pair to watch, because they are the two halves of one claim: turn partial rendering on (View ▸ Partial rendering) and Painted collapses from the whole widget tree to the handful under the damage while Frame does not move, which is the difference between a toolkit that repaints a window and one that repaints a caret.

Readable & cheap: the readout latches once per second on a Ui.postDelayed(java.lang.Runnable, long) heartbeat (numbers a human can actually read), so an idle app renders ~1 fps; the footer does not force continuous rendering. FPS shows the fastest window in the process (max across every scene's painted-frame delta); auxiliary windows (popups, desktop gadgets) are visible in it too. The per-frame paint allocates nothing: the strings and the unit's measured offset are computed on the 1 Hz latch, not per frame.

The footer reads with the tree around it — except for time. The demo carries a live direction picker in its toolbar, and a HUD that ignored the axis under it would read as a bug report. Reading right to left, the first card of each row is the rightmost one, and every card right-aligns its text and hangs its chart on the left. The charts themselves keep their axis: the newest tick is the rightmost bar in either direction, because time's flow is not a reading order — the reason a scrub bar and a clock do not mirror (docs/design/direction-axis.md).

  • Method Details

    • onMeasure

      protected Size onMeasure(Constraints constraints)
      Description copied from class: Widget
      Reports the size this widget wants within constraints. Called once per layout pass, and the result is cached against the constraints and the resolved axes (size step, layout direction, locale), so it must be a pure function of them and of this widget's own state.

      Resolve the ControlSize and the LayoutDirection once each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, and I18n.locale() answers it wherever text is resolved.

      Specified by:
      onMeasure in class Widget
    • onPaint

      protected void onPaint(Canvas canvas)
      Description copied from class: Widget
      Widget's own background/content, in local coordinates.
      Overrides:
      onPaint in class Widget
    • sampleNow

      public void sampleNow()
      Takes a sample now, off the heartbeat, and repaints with it. For the site's capture driver, which photographs this screen: every gauge shows a dash until the first beat and the CPU gauge until the second, because both need a reading a real interval apart from an earlier one, and the driver used to wait 2.6 s of wall clock per shot for the two beats to land. The first reading is the latch the first paint takes; this is the second, over however long the warm-up frames took, which is a real interval measured on the real clock and not a number invented for the picture. No-op off screen.