Skip to content

monitor.app 1.9.1: CPU rises with uptime, from 6% to 25% of a core over 4.5 hours #71

Open

Description

@evandhoffman

Observation

This was a soak test of the #70 build (the #69 fix, released as 1.9.1). One dashboard window stayed open on an M5 Max from 21:33 to 02:00 EDT (2026-09-25 to 2026-09-26). top took a 5-second reading every 5 minutes.

hour (EDT) readings mean CPU, % of a core phys_footprint at end of hour
21:00 6 5.7 371 MB
22:00 12 7.5 480 MB
23:00 12 10.0 389 MB
00:00 12 13.0 432 MB
01:00 11 25.0 494 MB
02:00 1 25.1 489 MB
  • CPU rose each hour. Readings from 01:25 to 02:00 were 21.1–28.3%.
  • Mach ports stayed flat at 357–424.
  • Footprint moved between 360 and 496 MB and did not grow steadily.

Profile

sample <pid> 5 at 01:39, 4 h 01 min uptime. Most wall time is idle (__workq_kernreturn, mach_msg2_trap). Of the app's own frames, the largest are:

  • ChartCard.chart(_:), the inner ForEach closure at ChartCard.swift:509–512 (the per-sample PlottableValue and mark construction): about 160 samples in total.
  • Sampler.tick → SMCSource.read → SMC.call: 42 samples.

The leaf frames are Swift value copies and generic-metadata lookups (swift_cvw_initWithCopyImpl, handleRefCountsDestroy, _swift_getGenericMetadata). These are consistent with copying per-sample values on each redraw.

Hypothesis (unverified)

The chart builds one mark per sample. If a card's range reads from HistoryStore and the range is not yet full, the number of marks grows with uptime until it fills. The per-redraw cost would then rise the same way. This does not explain the step at about 01:25. That step may be a range change, or a history tier that started to feed the chart.

Checks to separate the causes:

  • Log the mark count for each card on each redraw.
  • Downsample each series to about the chart's pixel width before building the marks.
  • Repeat the soak with a fixed 5-minute range on all cards.

Environment

  • Build: 9a5854d (the Turn the gauge hands with Core Animation, not SwiftUI (#69) #70 merge commit plus the version bump), run from .build/monitor.app.
  • Background load in the window: a Spotlight updater at about 100% of a core at times, and Time Machine (backupd) after 01:55. Both are outside Monitor's own CPU figure.

--opus

Activity

  1. evandhoffman commented on Sep 26, 2026

    @evandhoffman
    ContributorAuthor

    The same soak, continued to 03:30 EDT (6 h uptime):

    hour (EDT) readings mean CPU, % of a core phys_footprint at end of hour
    02:00 12 28.7 535 MB
    03:00 (to 03:30) 7 30.1 545 MB
    • Single readings in the 03:00 hour went as high as 43.1%.
    • The footprint rose from 489 MB at 02:00 to 545 MB at 03:30. Before 02:00 it moved in both directions.
    • Mach ports are still flat, at 402–417.

    --opus

  2. evandhoffman commented on Sep 26, 2026

    @evandhoffman
    ContributorAuthor

    The soak ended at 13:00 EDT with 15 h 28 min uptime. That was 187 readings, one every 5 minutes. monitor.app is still running; only the logger stopped.

    hour (EDT) readings mean CPU, % of a core phys_footprint at end of hour
    04:00 12 25.7 587 MB
    05:00 12 28.6 606 MB
    06:00 12 30.5 581 MB
    07:00 12 30.8 606 MB
    08:00 12 39.2 662 MB
    09:00 12 33.1 642 MB
    10:00 12 36.9 686 MB
    11:00 12 32.9 720 MB
    12:00 12 37.3 719 MB
    13:00 1 42.2 726 MB

    Summary over the whole soak:

    • Mean CPU rose from 5.7% in the first hour to 30–39% after 8 hours.
    • The footprint rose from about 371 MB to 726 MB.
    • Mach ports stayed flat, at about 357–426.

    Both CPU and footprint still rise with uptime. That fits the per-mark chart hypothesis above, and it may also be a retained-sample leak. A profile at a fixed chart range would separate the two.

    --opus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions