perf(reporting): stop round-tripping the whole behaviour log through json for Elasticsearch - #3232
Open
doomedraven wants to merge 1 commit into
Open
doomedraven wants to merge 1 commit into
doomedraven wants to merge 1 commit into
Conversation
…json for Elasticsearch
ElasticSearchDB.run() did
report = json.loads(json.dumps(report, default=str), object_hook=self.date_hook)
new_processes = insert_calls(report, elastic_db=elastic_handler)
so the entire api call log - the largest structure in the report,
commonly millions of entries - was serialised and re-parsed one line
before insert_calls moved it out into the calls index. Moving the
round-trip after insert_calls takes a 200k-call report from 7.36s to
2ms.
date_hook attempted strptime on every value in the tree, constructing
an exception for each int, list and non-date string. A leading digit,
a '-' and a ':' are all necessary for the format to parse, so guarding
on them converts exactly the same set of values. Checked against the
unguarded version across padded and unpadded dates, boundary years,
partial dates, paths and empty strings. Worth a further 4.2x on the
work that remains.
date_hook is NOT redundant with format_dates, which only touches
info.started, info.ended, info.machine.* and dropped[].pe.timestamp.
jsondump with store_compressed built the whole archive in a BytesIO
and then copied it out with getvalue(). It writes the zip directly to
disk now. No measurable speed change; the point is peak memory. The
archive entry name is unchanged.
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The main one
The round-trip serialises and re-parses the entire api call log — the largest structure in the report — one line before
insert_callsmoves it out into the calls index and discards it.date_hookguard onlyinsert_callsdate_hookRuns for every dict the parser produces and attempts
strptimeon every value, including ints and lists. Exception construction dominates. A leading digit, a-and a:are all necessary for that format to parse, so guarding on them converts exactly the same set of values — checked against the unguarded version across zero-padded and unpadded dates, boundary years, partial dates,T-separated timestamps, Windows paths, hex strings and empty strings.Note
date_hookis not redundant withformat_dates().format_datestouches onlyinfo.started,info.ended,info.machine.{started_on,shutdown_on}anddropped[].pe.timestamp; the hook converts date-shaped strings anywhere in the tree. It is kept.Warning
Moving the round-trip is a behaviour change for the calls index, and reviewers should weigh it:
default=str. They come from the BSON parser, so they are str/int/float/bool/None, but the safety net is gone.%Y-%m-%d %H:%M:%Sare no longer coerced todatetimebefore indexing, so they will map as strings rather than dates in the daily calls index. Arguably the correct behaviour, but it is mapping drift on an existing index.If that is not acceptable, the
date_hookguard alone still buys 4.2x and is behaviour-identical — happy to drop the reorder commit.jsondumpstore_compressedbuilt the whole archive in aBytesIOviacreate_zipand then copied it out withgetvalue(), on top of the uncompressed results dict already resident. Written straight to disk now. No measurable speed change — compression dominates either way — the point is peak memory. The archive entry name (reports/report.json) is preserved and asserted in a test.Tests
tests/test_reporting_elastic_jsondump.py— 5 tests, no Elasticsearch instance needed. Equivalence of the guardeddate_hookagainst the old one over 16 inputs, its behaviour as a realobject_hook, and both jsondump paths including the archive entry name.