-
Notifications
You must be signed in to change notification settings - Fork 3.9k
feat(compression): support per-column compression for non-cloud #66169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -580,6 +580,8 @@ class Lz4HCBlockCompression : public BlockCompressionCodec { | |
| static Lz4HCBlockCompression s_instance; | ||
| return &s_instance; | ||
| } | ||
| Lz4HCBlockCompression() = default; | ||
| explicit Lz4HCBlockCompression(int level) : _compression_level(level) {} | ||
| ~Lz4HCBlockCompression() { | ||
| SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER( | ||
| ExecEnv::GetInstance()->block_compression_mem_tracker()); | ||
|
|
@@ -663,6 +665,10 @@ class Lz4HCBlockCompression : public BlockCompressionCodec { | |
| if (localCtx->ctx == nullptr) { | ||
| return Status::InvalidArgument("LZ4_createStreamHC error"); | ||
| } | ||
| // A newly created stream defaults to the library's default level, so | ||
| // apply the requested level here; otherwise the first page compressed | ||
| // by this context would ignore the configured level. | ||
| LZ4_resetStreamHC_fast(localCtx->ctx, static_cast<int>(_compression_level)); | ||
| out = std::move(localCtx); | ||
| return Status::OK(); | ||
| } | ||
|
|
@@ -1077,6 +1083,8 @@ class ZstdBlockCompression : public BlockCompressionCodec { | |
| static ZstdBlockCompression s_instance; | ||
| return &s_instance; | ||
| } | ||
| ZstdBlockCompression() = default; | ||
| explicit ZstdBlockCompression(int level) : _compression_level(level) {} | ||
| ~ZstdBlockCompression() { | ||
| SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER( | ||
| ExecEnv::GetInstance()->block_compression_mem_tracker()); | ||
|
|
@@ -1123,9 +1131,8 @@ class ZstdBlockCompression : public BlockCompressionCodec { | |
| compressed_buf.size = max_len; | ||
| } | ||
|
|
||
| // set compression level to default 3 | ||
| auto ret = ZSTD_CCtx_setParameter(context->ctx, ZSTD_c_compressionLevel, | ||
| ZSTD_CLEVEL_DEFAULT); | ||
| _compression_level); | ||
| if (ZSTD_isError(ret)) { | ||
| return Status::InvalidArgument("ZSTD_CCtx_setParameter compression level error: {}", | ||
| ZSTD_getErrorString(ZSTD_getErrorCode(ret))); | ||
|
|
@@ -1262,6 +1269,7 @@ class ZstdBlockCompression : public BlockCompressionCodec { | |
| } | ||
|
|
||
| private: | ||
| int _compression_level = ZSTD_CLEVEL_DEFAULT; | ||
| mutable std::mutex _ctx_c_mutex; | ||
| mutable std::vector<std::unique_ptr<CContext>> _ctx_c_pool; | ||
|
|
||
|
|
@@ -1615,6 +1623,36 @@ Status get_block_compression_codec(segment_v2::CompressionTypePB type, | |
| return Status::OK(); | ||
| } | ||
|
|
||
| Status get_block_compression_codec(segment_v2::CompressionTypePB type, int level, | ||
| std::unique_ptr<BlockCompressionCodec>* codec_owned, | ||
| BlockCompressionCodec** codec) { | ||
| codec_owned->reset(); | ||
| // level <= 0 means "use codec default" -> fall back to the stateless singleton path. | ||
| if (level <= 0) { | ||
| return get_block_compression_codec(type, codec); | ||
| } | ||
| switch (type) { | ||
| case segment_v2::CompressionTypePB::ZSTD: { | ||
| auto instance = std::make_unique<ZstdBlockCompression>(level); | ||
| RETURN_IF_ERROR(instance->init()); | ||
| *codec = instance.get(); | ||
| *codec_owned = std::move(instance); | ||
| break; | ||
| } | ||
| case segment_v2::CompressionTypePB::LZ4HC: { | ||
| auto instance = std::make_unique<Lz4HCBlockCompression>(level); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Balance native context allocation and destruction under the same tracker for these new short-lived instances. Both |
||
| RETURN_IF_ERROR(instance->init()); | ||
| *codec = instance.get(); | ||
| *codec_owned = std::move(instance); | ||
| break; | ||
| } | ||
| default: | ||
| // types without a tunable level ignore it and use the singleton | ||
| return get_block_compression_codec(type, codec); | ||
| } | ||
| return Status::OK(); | ||
| } | ||
|
|
||
| // this can only be used in hive text write | ||
| Status get_block_compression_codec(TFileCompressType::type type, BlockCompressionCodec** codec) { | ||
| switch (type) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Avoid a private context pool per levelled column.
ScalarColumnWriterowns this instance, and after the first page itsZstdBlockCompression/Lz4HCBlockCompressionretains a native context plus reusable buffer until the whole segment clears its column writers. Wide schemas (and multiple open segments) therefore retain one heavyweight workspace per levelled column even though compression is serial; the old singleton pool reused contexts according to actual concurrency, and this memory is not included in the segment-size estimate. Please share/reset pools by codec+level (or release rather than pool per-column contexts) and add a wide-schema tracker test.