Performance improvements#710
Conversation
|
I don't know if we can use this: https://www.benjoffe.com/fast-date-64, but I keeping meaning to take a look. |
|
Thanks @genzgd! Great find. I'll definitely take a look. |
There was a problem hiding this comment.
Pull request overview
This PR focuses on speeding up hot-path native reads/writes (especially temporal types and Map/numeric inserts) by shifting more work into Cython and using direct epoch arithmetic and buffer-level fast paths, while also fixing a leap-year bug in epoch decoding.
Changes:
- Optimizes
DateTime/DateTime64decoding (naive UTC + UTC-equivalent tz) via epoch arithmetic and CPython datetime C-API construction, adding supporting helpers and tests. - Adds faster native write helpers (
write_native_col,build_map_columns) including a NumPymemcpyfast path for compatible arrays. - Reduces Map read/write materialization overhead and improves Decimal/BigDecimal read performance by avoiding per-row string building.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/unit_tests/test_driver/test_epoch_arithmetic.py | Adds unit tests for epoch arithmetic helpers and UTC-equivalent timezone helpers. |
| clickhouse_connect/driverc/dataconv.pyx | Adds epoch-to-datetime arithmetic helpers, DateTime64 decode loops, NumPy memcpy native writes, and Map flattening helper; fixes leap-year logic. |
| clickhouse_connect/driverc/buffer.pyx | Optimizes varint string-length parsing and adds a UTF-8 decode fast path in string reads. |
| clickhouse_connect/driver/tzutil.py | Reworks utcfromtimestamp and adds arithmetic-based helpers for UTC-equivalent tz-aware datetimes and explicit microseconds. |
| clickhouse_connect/driver/dataconv.py | Routes UTC-equivalent timezone reads through new arithmetic helper and adds pure-Python fallbacks for new C helpers. |
| clickhouse_connect/datatypes/temporal.py | Routes DateTime64 reads through shared conversion helpers (UTC-equivalent vs non-UTC). |
| clickhouse_connect/datatypes/numeric.py | Routes native fixed-width numeric inserts through write_native_col and optimizes Decimal/BigDecimal reads. |
| clickhouse_connect/datatypes/container.py | Uses new build_map_columns helper and reduces Map read allocations. |
| CHANGELOG.md | Documents the performance improvements and bug fix in UNRELEASED notes. |
|
Also, I've looked into the https://www.benjoffe.com/fast-date-64 stuff and it's super impressive. In the clickhouse-connect code though, after the current improvements in the branch, profiling shows the dt64 read hot path bottleneck is pretty much entirely now in the |
Summary
DateTimeandDateTime64native read hot paths, especially for naive UTC and UTC-equivalent timezones, by moving more conversion work onto direct epoch-arithmetic paths and dedicated Cython helpers.DateTime64naive-UTC decode loop and routed UTC-equivalent timezone reads through the same Cython C-API construction path used for naive UTC.DateTimeandDateTime64reads now constructdatetimeobjects directly via the CPython datetime C API, bypassing the intermediate component tuple and the Python-leveldatetime(...)constructor.DateTimeconversion bugs and a pre-existing leap-year bug in the epoch decoder where centuries divisible by 400 (2400, 2800, 3200, ...) were treated as non-leap. Expanded epoch/date arithmetic test coverage.INSERTserialization by routing native writes through a sharedwrite_native_colhelper.MapINSERTserialization with a sharedbuild_map_columnshelper and a faster Cython implementation for flattening keys/values plus offsets.Mapread materialization overhead by avoiding an intermediate pair-tuple allocation.DecimalandBigDecimalreads by replacing per-row string construction with directDecimal(int).scaleb(-scale).Checklist
Delete items not relevant to your PR: