Reduce size and copy cost of Settings objects#101228
Reduce size and copy cost of Settings objects#101228Algunenano wants to merge 5 commits intoClickHouse:masterfrom
Conversation
|
Workflow [PR], commit [5bafb82] Summary: ❌
AI ReviewSummaryThis PR refactors PR Metadata
Findings
ClickHouse Rules
Final Verdict
|
|
@azat @alexey-milovidov Maybe you would like to have a look at this PR. It's going to conflict all the time, so I'll prepare the private changes too and once it's reviewed fix new conflicts with master (it will conflict on anything changing session settings) |
Replace virtual dispatch through `SettingFieldBase` with a manual vtable (`SettingFieldOps`) that stores typed function pointers shared per setting field type. This eliminates the 8-byte vptr from every setting field instance in the `Data` struct. Key changes: - `SettingFieldBase` is now an empty base class (no virtual methods) - `SettingFieldOps` provides type-erased operations via named template functions (one static instance per concrete type, not per setting) - `FieldInfo` uses `offsetof` for data access instead of per-setting lambdas, and a single lazy lambda for default values - Per-setting lambda count reduced from 2 to 1 (was 2200, now 1100) Size reductions per field type (before → after): - `SettingFieldBool`: 16 → 2 bytes (556 settings → ~7.8 KB saved) - `SettingFieldUInt64`: 24 → 16 bytes (352 settings → ~2.8 KB saved) - `SettingFieldFloat`: 16 → 8 bytes - `SettingFieldString`: 40 → 32 bytes - All other types: 8 bytes saved each Total estimated savings: ~10 KB per `Settings` object. Settings.cpp compile time unchanged (~16s). References ClickHouse#58797 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the macro-generated Data struct (one member per setting) with a
code-generated layout that groups settings into typed arrays:
SettingFieldBool Bool_[795];
SettingFieldUInt64 UInt64_[428];
...
This eliminates inter-type padding waste and enables the compiler to use
`memcpy` per array for copy/move, reducing the copy constructor from
50 KB / 7654 instructions to 7 KB / 1135 instructions (7x smaller).
Key pieces:
- `SettingIndex<T>`: typed offset replacing pointer-to-member, defined
in SettingIndex.h
- `SettingsData.generated.h`: generated Data struct with typed arrays,
`SettingOffset::` constants, and default-value constructor
- `DECLARE_SETTINGS_TRAITS_GENERATED`: new macro variant that accepts
an externally-defined Data type
- Settings.cpp overrides: `IMPLEMENT_SETTING_SUBSCRIPT_OPERATOR` and
`INITIALIZE_SETTING_EXTERN` use generated offsets with pre-baked
base class adjustment for optimal `operator[]` (3 instructions)
The generator pipeline (not yet wired into CMake):
1. Preprocessor extracts TYPE/NAME/DEFAULT via marker macros
2. Shell script groups by type and emits the generated header
Other settings classes are unchanged — they continue using
pointer-to-member access.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cd8a072 to
1f27ade
Compare
|
I've removed COW changes since it overcomplicated many things and required a lot of changes. We use |
Settings definitions moved from Settings.cpp to SettingsList.inc. Update CI scripts that parse settings definitions: - check-settings-style: replace Settings.cpp with SettingsList.inc, strip "List" suffix from filename to get correct class name "Settings" - check_cpp.sh: grep SettingsList.inc for allow_* settings - feature_docs.py: recognize SettingsList.inc as embedded docs - pr_info.py: include SettingsList.inc in docs-related files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generator emitted `SettingFieldBool(0)` / `SettingFieldBool(1)` for obsolete settings defined with `MAKE_OBSOLETE(M, Bool, name, 0)`. clang-tidy requires `true`/`false` literals instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LLVM Coverage Report
Changed lines: 95.21% (278/292) · Uncovered code |
|
This looks good. It should help with anything using settings, as we'll have smaller functions and less iterative binary code. I expect this will conflict all the time with new settings being added, so once it's reviewed and accepted I'll do the final conflict resolution and merge. |
Reduce the size and copy cost of
Settingsand all other settings objects.1. Remove vtable from setting field types
Replace virtual dispatch through
SettingFieldBasewith a manual vtable (SettingFieldOps) shared per type. This eliminates the 8-byte vptr from every setting field instance.SettingFieldBoolgoes from 16 to 2 bytes,SettingFieldUInt64from 24 to 16 bytes. Total savings: ~10 KB perSettingsobject.2. Generated typed-array Data layout for Settings
A CMake code generator groups settings into typed arrays (
Bool_[795],UInt64_[428], etc.) instead of one member per setting. This eliminates inter-type padding waste and lets the compiler usememcpyper array for copies. The copy constructor shrinks from 50 KB / 7654 instructions to 7 KB / 1135 instructions (7x). Settings definitions are extracted toSettingsList.incso the generator can include them via the preprocessor, ensuring it always sees exactly what the compiler sees.Closes #58797
Changelog category (leave one):
Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):
Reduce memory footprint and copy cost of Settings objects by removing vtable overhead from setting fields, and using a generated typed-array layout.
Documentation entry for user-facing changes