Skip to content

Conversation

@HuaHuaY
Copy link
Contributor

@HuaHuaY HuaHuaY commented Jan 14, 2026

Rationale for this change

Reduce zstd compression/decompression resource consumption by reusing context.

What changes are included in this PR?

ZSTDCodec will create a context lazily.

Are these changes tested?

Yes. I improved the benchmark to test different compression level. And I test in my private environment. The above is the benchmark of this PR, and the following is the original one.

img_v3_02tu_6f9779ff-c53b-4ccc-b707-f43354e553cg

Are there any user-facing changes?

No.

@github-actions
Copy link

⚠️ GitHub issue #37169 has been automatically assigned in GitHub to PR creator.

@HuaHuaY
Copy link
Contributor Author

HuaHuaY commented Jan 14, 2026

@pitrou @wgtmac @mapleFU Please take a look.

@HuaHuaY HuaHuaY changed the title GH-37169: [C++] zstd compression uses context GH-37169: [C++] Zstd compression uses context Jan 14, 2026
@github-actions
Copy link

⚠️ GitHub issue #37169 has been automatically assigned in GitHub to PR creator.

: compression_level) {}

~ZSTDCodec() override {
ZSTD_freeCCtx(compression_context_);
Copy link
Contributor Author

@HuaHuaY HuaHuaY Jan 14, 2026

Choose a reason for hiding this comment

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

Zstd documentation states that these two free functions can accept nullptr. But if someone thinks that null pointer judgment is needed here, it's fine for me. Or we can wrap it with std::unique_ptr.
https://facebook.github.io/zstd/zstd_manual.html

size_t     ZSTD_freeCCtx(ZSTD_CCtx* cctx);  /* accept NULL pointer */
size_t     ZSTD_freeDCtx(ZSTD_DCtx* dctx);  /* accept NULL pointer */

Copy link
Member

@mapleFU mapleFU left a comment

Choose a reason for hiding this comment

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

General idea ok to me, would createCctx Dctx in ctor expansive?

size_t ret = ZSTD_compress(output_buffer, static_cast<size_t>(output_buffer_len),
input, static_cast<size_t>(input_len), compression_level_);
if (compression_context_ == nullptr) {
compression_context_ = ZSTD_createCCtx();
Copy link
Member

Choose a reason for hiding this comment

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

I don't would this class be used multi threaded...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The comments in your issue show that the codec methods are not multi-thread safe. But there are many fail unit tests. I will check whether codec is shared in multiple threads.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TEST_F(TestWriteRecordBatch, WriteWithCompression) will share codec in multiple threads. So the implementation of this PR is not suitable. I will fix it.

@github-actions github-actions bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels Jan 14, 2026
@HuaHuaY
Copy link
Contributor Author

HuaHuaY commented Jan 14, 2026

General idea ok to me, would createCctx Dctx in ctor expansive?

I guess that it will create a context every time we call Compress in the original code.

@HuaHuaY HuaHuaY force-pushed the arrow_zstd_context branch from 51a7bf9 to ba4bdde Compare January 14, 2026 10:24
@HuaHuaY
Copy link
Contributor Author

HuaHuaY commented Jan 14, 2026

In previous comments, we found that the Compress and Decompress functions of Codec need to be thread-safe in the use of Arrow IPC. There are two solutions:

  1. Use thread_local + static. However, I found that using thread_local introduces synchronization overhead, making context reuse slower than the original code.
  2. Selectively reuse the context by declaring a new class ZstdCodecOptions that inherits from CodecOptions, and using comments to indicate that it should only be enabled when Codec is not shared.

I chose option 2.

But after repeated testing, I found that in my private environment, reusing the context only resulted in a significant performance improvement when the compression level was greater than or equal to 6. There was no performance improvement, and even a performance decrease, when the compression level was less than 6 or during decompression. In the screenshot, a template parameter explicitly set to true indicates context reuse.

image

Therefore, I've decided to close this PR. Those interested can still view the PR's commits.

@HuaHuaY HuaHuaY closed this Jan 14, 2026
@pitrou
Copy link
Member

pitrou commented Jan 14, 2026

For the record, a similar request was made in #48192

@HuaHuaY HuaHuaY deleted the arrow_zstd_context branch January 14, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants