Repository navigation
Conversation
e8c74ec to
0b2d5ba
Compare
PR #108 tandem review, round 4 (level 3)Reviewed at level 3, tandem mode, as one logical change across three PRs:
Verdicts:
Every behavioural finding below was executed on both the head and the base revision.
CriticalNone. Moderate1. [client]
|
Re-pin the submodule at questdb/java-questdb-client#108 after its branch merged the client's main, which moved the client version to 1.3.11-SNAPSHOT. Set questdb.client.version to match in every pom. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4afe650 to
d632ea7
Compare
PR #108 review (level 3)Reviewed the four commits on top of #121: Verdict: approve. No Critical or Moderate findings, three Minor test-code items. PR metadata: the title is fine. The Minor1. A table-order check passes even when
2.
3. Header size written as a literal
What was checked
Trade-off: the new table order changes which large batches get rejectedMechanism:
When it matters: the delta plus the big table's body is over the server cap, but the delta plus the small table's body fits. The outcome then depends on row order. Scenario: these are the shapes of
Run at both revisions:
Why this is not a blocking finding:
Options:
|
MicrobatchBuffer read System.nanoTime() on the first row of every microbatch to serve getAgeNanos(), which nothing calls. Drop the field, the stamp and the getter, together with the test of the getter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DjhXUiBaimJEwHoXYv4CeN
The table block header re-encoded the table name and every column name from Java strings on each frame. Cache the wire form of the table name (built in the constructor) and of the column definitions (rebuilt with the column definitions cache), and copy the two byte arrays with the row-count varint between them. The frame bytes are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DjhXUiBaimJEwHoXYv4CeN
ColumnBuffer.reset() zeroed the null bitmap and cleared the local symbol dictionary on every flush. Zero the bitmap only after a batch that held nulls, and clear the dictionary only when it has entries. Tests pin the bitmap and dictionary behaviour across resets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DjhXUiBaimJEwHoXYv4CeN
Every flush walked every table the sender had ever seen, with a hash probe per key, to find the ones with rows, and emptied the two flush lists with ObjList.clear(), which fills the whole backing array. sendRow() now lists a table in pendingTables when it receives its first row since the last successful flush; a flag on QwpTableBuffer keeps each table listed once. collectNonEmptyTables() walks that list, and the flush lists are emptied with setPos(0). The list and the flags are cleared together only when a flush succeeds or finds nothing to ship, so a flush that throws before publishing leaves the list for the retry. reset() leaves the list alone and the collect skips listed tables without rows; close() empties it. Tables in a frame now ship in the order they first received a row since the last flush, instead of the order the sender first saw them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DjhXUiBaimJEwHoXYv4CeN
6ac4f95 to
ba25bf1
Compare
[PR Coverage check]😍 pass : 68 / 69 (98.55%) file detail
|
PR #108 review: java-questdb-client (level 3, client only)Reviewed Verdict: approve with comments. Nothing blocks the merge. I'd like Moderate 1 fixed before merge. PR metadata: fine. The title follows Conventional Commits, the labels are Moderate1. The buffer-growth branch of the new
Minor1. The
2. Two table-order assertions are weak (
3. The new tests re-implement shared helpers (carried over from the 5 Nov review).
Coverage mapThe test gate passes. There is one gap, Moderate 1, and no Critical gaps.
Mutation runs confirm that the new tests pin the pending-tables list, the null bitmap, and the column-definition cache. Each mutation below turns at least one test red:
Summary
Mutation and probe logs are kept locally and are available on request. 🤖 Generated with Claude Code |
Speeds up the producer side of
flush()on the WebSocket sender. This cost dominates when an application flushes every few rows, or borrows a sender from theQuestDBpool and closes it per message. The wire format and the public API do not change.What changes
Four cuts on the flush path, each in its own commit:
MicrobatchBufferno longer readsSystem.nanoTime()on the first row of every microbatch. The stamp only fedgetAgeNanos(), which had no caller.ColumnBuffer.reset()zeroes the null bitmap only after a batch that held nulls, and clears the local symbol dictionary only when it has entries.setPos(0).One ordering change follows from the last cut: tables in a multi-table frame now ship in the order they first received a row since the last flush (rows that
reset()discarded count), instead of the order the sender first saw them.Measurements
Apple M4 Max, JDK 25. Producer thread only, median ns per row, 12 runs of 500k rows against the client's loopback test server. "Before" is #121 at
05b31067, measured before #121 merged;mainhas since changed only build-time validation, failure paths and native-memory accounting.Sender,flush()per row, 1 tableSender,flush()per row, 100 tables round-robinQuestDBfacade,borrowSender()andclose()per row, 1 tableSender, rows only (auto_flush_rows=1000)End to end against QuestDB
master(which includes questdb/questdb#8110), 1M rows written with a borrow and aclose()per row, time until every row is applied: 304 ms before, 199 ms after. The faster producer lets the I/O thread send full batches, which the server commits together (about 50 WAL commits instead of about 1,900). With 100 tables in round-robin the end-to-end time does not change (1.34 s on both), because the server commits each frame on its own when consecutive frames are for different tables; questdb/questdb#8195 (open) addresses that.🤖 Generated with Claude Code