Skip to content

darwin: order the memory classes so the used ones come first - #2074

Open
ravi-arnan wants to merge 1 commit into
htop-dev:mainfrom
ravi-arnan:darwin-memory-class-order
Open

darwin: order the memory classes so the used ones come first#2074
ravi-arnan wants to merge 1 commit into
htop-dev:mainfrom
ravi-arnan:darwin-memory-class-order

Conversation

@ravi-arnan

Copy link
Copy Markdown
Contributor

Closes #2073.

darwin/Platform.c is the only platform whose Platform_memoryClasses[] interleaves the classes that count as used with the ones that count as cache, so speculative and purgeable are drawn between wired, active and compressed. The used total the meter prints is the sum of the countsAsUsed classes and is correct; it just does not correspond to a contiguous run of bars from the left-hand edge, which is what the FAQ describes. The cross-platform table is in the triage comment on the issue.

This reorders the enum so the three used classes come first, keeping the relative order inside each group.

The colours had to move with them

.color is not the only thing that decides a segment's colour, which was not obvious to me until I looked at the two render paths:

  • MemoryMeter_display() (text mode) colours each value with Platform_memoryClasses[i].color.
  • BarMeterMode_draw() (Meter.c:181) colours segment i with Meter_attributes(this)[i], which for this meter is MemoryMeter_attributes[] = MEMORY_1 .. MEMORY_6 by position, and never looks at .color.

Every platform currently keeps .color in step with the array position, so the two paths agree and the difference is invisible. That means "reorder the classes but let every label keep the colour it has today" is not actually on the table: bar mode would recolour by position anyway while text mode would not, and the two modes would then disagree about what colour speculative is. So .color moves with the class and stays in MEMORY_1 .. MEMORY_6 sequence, which keeps the existing invariant.

With the default colour scheme that means, in both modes:

class before after
wired green green
active bold gray magenta
compressed yellow bold gray
speculative magenta bold blue
purgeable bold blue yellow
inactive cyan cyan

If you would rather nothing changed colour, the alternative is to make bar/graph/LED mode honour .color instead of the positional MemoryMeter_attributes[]. That is a change to shared meter code rather than to this platform, so I have not done it here, but say the word and I will.

Verification

Built from main (6f33ddd) and from this branch on a MacBookPro12,1 running macOS 12.7.6, captured back to back. Not an M-series machine, so #2073 is not Apple Silicon specific.

Text mode:

before  Mem:16.0G wired:1.45G speculative:1.33G active:2.99G purgeable:181M compressed:0K inactive:3.96G
after   Mem:16.0G wired:1.45G active:3.00G compressed:0K speculative:1.33G purgeable:181M inactive:3.96G

Bar mode, with the SGR runs decoded so the class behind each segment is visible (compressed is 0K on this machine, so it has zero width in both):

before  Mem[ wired ×5 | speculative ×4 | active ×9 | purgeable ×1 | inactive ×12    4.48G/16.0G]
after   Mem[ wired ×5 | active ×10 | speculative ×4 | purgeable ×1 | inactive ×12   4.51G/16.0G]

so the used classes are one contiguous run from the left edge afterwards, and the text and bar modes agree on every class's colour in both builds.

Not touched

pcp/Platform.c carries a second Darwin table (Darwin_memoryClasses[], memcpy'd into Platform_memoryClasses when the PCP target reports Darwin) with the same interleaving. I left it alone because its flags disagree with this file, speculative and inactive are countsAsUsed = true there, so "used first" does not mean the same thing, and I have no PCP Darwin host to test against. Happy to follow up if you want it aligned.

@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 01e5d2ba-d17a-464c-a851-d5d8ea9fa83b

📥 Commits

Reviewing files that changed from the base of the PR and between 6f33ddd and 0600da7.

📒 Files selected for processing (1)
  • darwin/Platform.c

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The macOS memory categories now appear as wired, active, compressed, speculative, purgeable, and inactive. Color assignments were updated to match this sequence. No exported or public declarations changed.

Assessment against linked issues

Objective Addressed Explanation
Reorder macOS memory meters so wired, active, and compressed appear before speculative and purgeable memory [#2073]

Poem

Wired leads the measured stream,
Active follows, clear and bright.
Compressed joins the ordered team,
Speculative moves from sight.
Purgeable and inactive wait,
Each color keeps its proper place.

Merge Risk: ⚪ Minimal · up to 0600d

This change only reorders Darwin memory classes and their associated colors so used memory appears contiguously while preserving text and bar display consistency; no actionable merge-blocking risk remains beyond normal checks and review.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@natoscott natoscott left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ravi-arnan does Platform_memoryClasses need to change here? the values from the enum are baked into it's declaration - isn't it sufficient to just change the enum? Thanks!

@ravi-arnan

Copy link
Copy Markdown
Contributor Author

Good question, and you are right about the ordering: the array uses designated initializers, so the enum alone decides both the storage slot and the display order. Moving the initializer lines is cosmetic. I did it only so the file reads in the order it renders, and I am happy to drop that part if you would rather keep the diff minimal.

The .color values are the part that is not cosmetic, and I should have made that clearer in the description.

MemoryMeter_display() colours each value with Platform_memoryClasses[i].color, but bar, graph and LED modes colour segment i with Meter_attributes(this)[i] (Meter.c:181), which for this meter is MemoryMeter_attributes[] = MEMORY_1 .. MEMORY_6 by position, and never reads .color. Every platform keeps the two in step today, so they agree and the distinction is invisible.

I did build the enum-only version first. On this Mac it renders active in two different colours at the same time:

class text mode bar mode
wired green (MEMORY_1) green (MEMORY_1)
active bold gray (MEMORY_3) magenta (MEMORY_2)
compressed yellow (MEMORY_5) 0K on this machine, no segment
speculative magenta (MEMORY_2) bold blue (MEMORY_4)
purgeable bold blue (MEMORY_4) yellow (MEMORY_5)
inactive cyan (MEMORY_6) cyan (MEMORY_6)

Those are the SGR runs decoded out of the captures rather than eyeballed, from one binary in one sitting. Moving .color along with the class is what puts the two paths back in step.

So, your call:

  1. As it stands.
  2. Enum plus .color, but leave the initializer lines where they are. Smaller diff, at the cost of the colours reading out of sequence in the file.
  3. Enum only, and accept that text and bar disagree on Darwin.
  4. Make bar, graph and LED honour .color instead of the positional array. That is the only option that keeps every Darwin label the colour it has today, but it touches shared meter code rather than this platform.

I lean 1 or 2. 4 is worth considering if not changing what existing users see matters more than the size of the change, and I am glad to do it either way.

The memory meter draws the categories in the order they appear in
Platform_memoryClasses, and on Darwin that order interleaves the three
classes that count as used with the three that count as cache:

  wired, speculative, active, purgeable, compressed, inactive

The used total the meter prints is the sum of the countsAsUsed classes
and is correct, but speculative and purgeable are drawn between wired,
active and compressed, so that total does not correspond to a contiguous
run of bars from the left-hand edge.

Darwin is the only platform that interleaves the two kinds. linux,
freebsd, dragonflybsd, netbsd, openbsd and solaris all list every
countsAsUsed class before any cache class.

Reorder the enum so the used classes come first, keeping the relative
order within each group, and move each .color along with it so that the
colours stay in MEMORY_1..MEMORY_6 sequence. That sequence is not
cosmetic: BarMeterMode_draw() colours segment i with
MemoryMeter_attributes[i], which is MEMORY_(i+1) by position and ignores
.color entirely, while MemoryMeter_display() uses .color. Every platform
currently keeps the two in step, so the modes agree; leaving .color
attached to its old label here would have made the bar and the text
disagree about what colour, say, speculative is.

Closes htop-dev#2073

Assisted-by: Claude:opus-5
@ravi-arnan
ravi-arnan force-pushed the darwin-memory-class-order branch from 0600da7 to a3c0579 Compare August 24, 2026 12:40
@BenBE BenBE added enhancement Extension or improvement to existing feature code quality ♻️ Code quality enhancement MacOS 🍏 MacOS / Darwin related issues labels Aug 24, 2026
@BenBE BenBE added this to the 3.6.0 milestone Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code quality ♻️ Code quality enhancement enhancement Extension or improvement to existing feature MacOS 🍏 MacOS / Darwin related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory meters on macOS render in unexpected order

3 participants