Skip to content

Optimises blittable types for multi-dim arrays - #390

Merged
alex-clickhouse merged 3 commits into
ClickHouse:mainfrom
DanielBunting:DB/add-multidim-blittable-types
Aug 4, 2026
Merged

Optimises blittable types for multi-dim arrays#390
alex-clickhouse merged 3 commits into
ClickHouse:mainfrom
DanielBunting:DB/add-multidim-blittable-types

Conversation

@DanielBunting

Copy link
Copy Markdown
Contributor

Summary

Removes the per-element boxing on multidimensional array inserts (#367).
Rectangular CLR arrays (int[,], double[,,], …) of fixed-width primitive leaves — Int8/16/32/64, UInt8/16/32/64, Float32/64, Bool are now serialized by blitting each contiguous inner row in a single write instead of boxing every element through Array.GetValue(int[]).
Output bytes are unchanged; it's an internal optimization with no public API change. Jagged shapes, nullable/LowCardinality/wrapped leaves, big-endian hosts, and Int128/UInt128 fall through to the existing path.

Not included — Int128/UInt128: these are BigInteger-backed in the driver, and BigInteger is unblittable (it's a sign int + a heap uint[], not an inline 16-byte value). Bringing them into the fast path means switching their FrameworkType to System.Int128/System.UInt128, which is a breaking change to the read return type and needs net6 handling (conditional compilation or dropping net6 support).

Checklist

Delete items not relevant to your PR:

  • Unit and integration tests covering the common scenarios were added
  • A human-readable description of the changes was provided to include in CHANGELOG

Copilot AI review requested due to automatic review settings June 29, 2026 23:41
@DanielBunting
DanielBunting requested a review from mzitnik as a code owner June 29, 2026 23:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an internal performance optimization to the binary write path for rectangular CLR multidimensional arrays (T[,], T[,,], …) when the leaf element type is a fixed-width primitive, eliminating per-element boxing and virtual dispatch by blitting contiguous innermost rows directly to the output stream.

Changes:

  • Added a blittable fast-path in MultiDimArrayHelper.WriteMultidimensional for fixed-width primitive leaves on little-endian hosts.
  • Added unit + integration tests to assert byte-for-byte equivalence vs the existing jagged/boxing path and to guard allocations.
  • Added a BenchmarkDotNet benchmark to measure jagged boxing vs multidim blitting, and documented the improvement in CHANGELOG/RELEASENOTES.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ClickHouse.Driver/Types/MultiDimArrayHelper.cs Adds the blit-based fast path for blittable primitive leaves during binary serialization.
ClickHouse.Driver.Tests/Types/MultiDimArrayHelperTests.cs Adds equivalence tests across supported leaf types and an allocation regression test.
ClickHouse.Driver.Tests/SQL/NestedArrayParameterTests.cs Adds end-to-end binary insert round-trip coverage for the blit path across primitive leaf types.
ClickHouse.Driver.Benchmark/MultidimArrayInsert.cs Adds a benchmark comparing jagged (boxing) vs multidim (blit) inserts.
CHANGELOG.md Documents the optimization for release notes.
RELEASENOTES.md Documents the optimization for NuGet package release notes.

Comment thread ClickHouse.Driver.Benchmark/MultidimArrayInsert.cs Outdated
Comment thread ClickHouse.Driver.Benchmark/MultidimArrayInsert.cs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread ClickHouse.Driver/Types/MultiDimArrayHelper.cs
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@alex-clickhouse

Copy link
Copy Markdown
Collaborator

Looks great, thank you!

@alex-clickhouse
alex-clickhouse merged commit 7d3a2d9 into ClickHouse:main Aug 4, 2026
18 checks passed
alex-clickhouse added a commit that referenced this pull request Aug 5, 2026
main added 22 new Unreleased entries since this branch was cut. Each is now
its own changelog.d/ fragment, extracted verbatim by line number rather than
retyped, so the assembled Unreleased section reproduces main's exactly (as a
set of lines; sorting by PR number reorders entries within their sections).

New fragments, one per (PR, category):

  #390 improvements   multidim blittable inserts
  #472 improvements   per-scalar Span<byte> reads
  #484 fixes          byte[]/TimeOnly HTTP parameters
  #485 fixes          JSON strings under ReadStringsAsByteArrays
  #490 breaking       raw results return compressed bytes
  #490 features       AcceptEncoding response compression
  #490 improvements   lz4 by default, HttpClient, errors, deflate
  #492 fixes          HTTP response disposal
  #493 fixes          Enum type declarations
  #494 fixes          raw-stream double dispose
  #497 fixes          GetSchema("Columns") restrictions
  #498 fixes          JSON paths starting with setting names
  #503 fixes          quoted JSON typed paths
  #504 fixes          quoted Tuple/Nested element names
  #509 fixes          {name:Type} scanner vs server lexer
  #511 fixes          {name:Type} hints after a non-hint brace
  #513 fixes          @name placeholders, heredocs, $ in names

#390's entry was appended to the *released* v1.3.0 section on main (v1.3.0
shipped 2026-06-29), so it would have documented an unreleased change under a
shipped version and never appeared in 1.4.0's notes. It moves to Unreleased as
a fragment; the rest of v1.3.0 is byte-identical.

RELEASENOTES.md regenerated with --sync-notes. `--check` passes, the solution
builds, and the packed .nupkg's releaseNotes open on v1.3.0 with no Unreleased
stub and no #390 bullet.
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.

3 participants