Skip to content

Improve hr performance - #885

Open
rumpelsepp wants to merge 2 commits into
masterfrom
hr-performance
Open

Improve hr performance#885
rumpelsepp wants to merge 2 commits into
masterfrom
hr-performance

Conversation

@rumpelsepp

Copy link
Copy Markdown
Member

I tried coding with AI and I could optimize hr:

Replace three hot-path spots in PenlogRecord that run once per record
when hr reads a penlog file, with cheaper stdlib-only equivalents:

  • PenlogPriority.to_level(): match-statement -> precomputed dict
    lookup. Also used by gallia's live console logging, not just hr.
  • PenlogRecord.parse_json(): PenlogPriority(value) enum construction
    -> precomputed {value: member} dict, and six "key in dict" + subscript
    pairs -> .get(). Both are behavior-preserving (same ValueError on an
    invalid priority, same None-on-missing-field semantics).
  • _format_record(): dt.strftime("%b %d %H:%M:%S.%f") -> manual f-string
    with a fixed month-abbreviation table. Behavior change: timestamps
    always render English month abbreviations now, instead of respecting
    the OS locale.

Benchmark: hr -p trace over a synthetic 2,000,000-record/420MB penlog
file, output redirected to /dev/null, best of repeated runs:

before: 11.10s
after: 8.85s (~20% faster, byte-identical output aside from the
intentional month-name change)

rumpelsepp and others added 2 commits July 27, 2026 16:19
`_parse_file_structure()` built the record-offset table starting from
the mmap's current position instead of the file start, so lazily
triggering it after any forward reads (as `-r`/--reverse does) produced
a truncated table. On top of that, `records(reverse=True)` defaulted to
starting at record 0 and relied on Python's negative-index wraparound
to reach later records, so `hr -r` never actually started from the end
of the file. Together these made `hr -r` silently emit duplicate,
missing, or wrongly ordered records on any real log file.

Also switch `_record_offsets` from a list to `array("Q")`, matching
cursed_hr.py's approach, which cuts memory and time for building the
offset table (used by -t/--tail, -r/--reverse and len()) roughly in
half.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replace three hot-path spots in PenlogRecord that run once per record
when hr reads a penlog file, with cheaper stdlib-only equivalents:

- PenlogPriority.to_level(): match-statement -> precomputed dict
  lookup. Also used by gallia's live console logging, not just hr.
- PenlogRecord.parse_json(): PenlogPriority(value) enum construction
  -> precomputed {value: member} dict, and six "key in dict" + subscript
  pairs -> .get(). Both are behavior-preserving (same ValueError on an
  invalid priority, same None-on-missing-field semantics).
- _format_record(): dt.strftime("%b %d %H:%M:%S.%f") -> manual f-string
  with a fixed month-abbreviation table. Behavior change: timestamps
  always render English month abbreviations now, instead of respecting
  the OS locale.

Benchmark: `hr -p trace` over a synthetic 2,000,000-record/420MB penlog
file, output redirected to /dev/null, best of repeated runs:

  before: 11.10s
  after:   8.85s  (~20% faster, byte-identical output aside from the
                   intentional month-name change)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

1 participant