zstd-ruby 1.5.6.2 → 1.5.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c50aade1eb5c3a36dfaba5dc325c1bc416ceaa3558539ae5b389bb4378f6c37
4
- data.tar.gz: 490b1268c79f5e481969fb1cf2fe2adb9bba5a51ab0e0197fd0338913a228611
3
+ metadata.gz: 729474c9a3f3196fe69a06dfdd280c5879bc368b1884b8d508b75164aa7e1dcd
4
+ data.tar.gz: 1cdf1b0554dd89aa1f7b6450be8eb183773a0f3b895024715ae7b3243cec598b
5
5
  SHA512:
6
- metadata.gz: 14db577b5e10bc3a92df632d391dfdb55802da3768e5b829c9b849f440b0b5234be8d924a6b0c5d237cab7befdd540d1535de0ba56dafd30fbfe13c2e635e229
7
- data.tar.gz: e6959f0da13aaa2a609fec024a3f293e4366760e3efd7626fc545c29ad5a1b0290119bc088cf60cb6665c1f2a5d93f0faf72152be3cf470ce5cf43657695a588
6
+ metadata.gz: d69bc35190b5dbc8ce36f9e5acf6ef26a2c85a899ddd409f8eee4a83b005166b20d22e2659cae1b101fb1b97f6a7bf12cf4066e3da94b2a1991d41bf255cd1ce
7
+ data.tar.gz: 2ee85e56a8ae268da1e4b69bf35a016a5d9bc677f240435725e082b5c5279e60d7f8be32dbe57283e618b7cf59b3937b57aa859f6cbb0aafa64458a903747fa2
@@ -2,6 +2,10 @@
2
2
  #define ZSTD_RUBY_H 1
3
3
 
4
4
  #include <ruby.h>
5
+ #ifdef HAVE_RUBY_THREAD_H
6
+ #include <ruby/thread.h>
7
+ #endif
8
+ #include <stdbool.h>
5
9
  #include "./libzstd/zstd.h"
6
10
 
7
11
  static int convert_compression_level(VALUE compression_level_value)
@@ -12,11 +16,6 @@ static int convert_compression_level(VALUE compression_level_value)
12
16
  return NUM2INT(compression_level_value);
13
17
  }
14
18
 
15
- static size_t zstd_compress(ZSTD_CCtx* const ctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input, ZSTD_EndDirective endOp)
16
- {
17
- return ZSTD_compressStream2(ctx, output, input, endOp);
18
- }
19
-
20
19
  static void set_compress_params(ZSTD_CCtx* const ctx, VALUE level_from_args, VALUE kwargs)
21
20
  {
22
21
  ID kwargs_keys[2];
@@ -45,6 +44,36 @@ static void set_compress_params(ZSTD_CCtx* const ctx, VALUE level_from_args, VAL
45
44
  }
46
45
  }
47
46
 
47
+ struct compress_params {
48
+ ZSTD_CCtx* ctx;
49
+ ZSTD_outBuffer* output;
50
+ ZSTD_inBuffer* input;
51
+ ZSTD_EndDirective endOp;
52
+ size_t ret;
53
+ };
54
+
55
+ static void* compress_wrapper(void* args)
56
+ {
57
+ struct compress_params* params = args;
58
+ params->ret = ZSTD_compressStream2(params->ctx, params->output, params->input, params->endOp);
59
+ return NULL;
60
+ }
61
+
62
+ static size_t zstd_compress(ZSTD_CCtx* const ctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input, ZSTD_EndDirective endOp, bool gvl)
63
+ {
64
+ #ifdef HAVE_RUBY_THREAD_H
65
+ if (gvl) {
66
+ return ZSTD_compressStream2(ctx, output, input, endOp);
67
+ } else {
68
+ struct compress_params params = { ctx, output, input, endOp };
69
+ rb_thread_call_without_gvl(compress_wrapper, &params, NULL, NULL);
70
+ return params.ret;
71
+ }
72
+ #else
73
+ return ZSTD_compressStream2(ctx, output, input, endOp);
74
+ #endif
75
+ }
76
+
48
77
  static void set_decompress_params(ZSTD_DCtx* const dctx, VALUE kwargs)
49
78
  {
50
79
  ID kwargs_keys[1];
@@ -63,4 +92,33 @@ static void set_decompress_params(ZSTD_DCtx* const dctx, VALUE kwargs)
63
92
  }
64
93
  }
65
94
 
95
+ struct decompress_params {
96
+ ZSTD_DCtx* dctx;
97
+ ZSTD_outBuffer* output;
98
+ ZSTD_inBuffer* input;
99
+ size_t ret;
100
+ };
101
+
102
+ static void* decompress_wrapper(void* args)
103
+ {
104
+ struct decompress_params* params = args;
105
+ params->ret = ZSTD_decompressStream(params->dctx, params->output, params->input);
106
+ return NULL;
107
+ }
108
+
109
+ static size_t zstd_decompress(ZSTD_DCtx* const dctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input, bool gvl)
110
+ {
111
+ #ifdef HAVE_RUBY_THREAD_H
112
+ if (gvl) {
113
+ return ZSTD_decompressStream(dctx, output, input);
114
+ } else {
115
+ struct decompress_params params = { dctx, output, input };
116
+ rb_thread_call_without_gvl(decompress_wrapper, &params, NULL, NULL);
117
+ return params.ret;
118
+ }
119
+ #else
120
+ return ZSTD_decompressStream(dctx, output, input);
121
+ #endif
122
+ }
123
+
66
124
  #endif /* ZSTD_RUBY_H */
@@ -2,7 +2,7 @@ require "mkmf"
2
2
 
3
3
  have_func('rb_gc_mark_movable')
4
4
 
5
- $CFLAGS = '-I. -O3 -std=c99 -DZSTD_STATIC_LINKING_ONLY'
5
+ $CFLAGS = '-I. -O3 -std=c99 -DZSTD_STATIC_LINKING_ONLY -DZSTD_MULTITHREAD -pthread -DDEBUGLEVEL=0'
6
6
  $CPPFLAGS += " -fdeclspec" if CONFIG['CXX'] =~ /clang/
7
7
 
8
8
  Dir.chdir File.expand_path('..', __FILE__) do
@@ -106,7 +106,7 @@ no_compress(struct streaming_compress_t* sc, ZSTD_EndDirective endOp)
106
106
  do {
107
107
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
108
108
 
109
- size_t const ret = zstd_compress(sc->ctx, &output, &input, endOp);
109
+ size_t const ret = zstd_compress(sc->ctx, &output, &input, endOp, false);
110
110
  if (ZSTD_isError(ret)) {
111
111
  rb_raise(rb_eRuntimeError, "flush error error code: %s", ZSTD_getErrorName(ret));
112
112
  }
@@ -130,7 +130,7 @@ rb_streaming_compress_compress(VALUE obj, VALUE src)
130
130
  VALUE result = rb_str_new(0, 0);
131
131
  while (input.pos < input.size) {
132
132
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
133
- size_t const ret = zstd_compress(sc->ctx, &output, &input, ZSTD_e_continue);
133
+ size_t const ret = zstd_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
134
134
  if (ZSTD_isError(ret)) {
135
135
  rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(ret));
136
136
  }
@@ -157,7 +157,7 @@ rb_streaming_compress_write(int argc, VALUE *argv, VALUE obj)
157
157
 
158
158
  while (input.pos < input.size) {
159
159
  ZSTD_outBuffer output = { (void*)output_data, sc->buf_size, 0 };
160
- size_t const ret = zstd_compress(sc->ctx, &output, &input, ZSTD_e_continue);
160
+ size_t const ret = zstd_compress(sc->ctx, &output, &input, ZSTD_e_continue, false);
161
161
  if (ZSTD_isError(ret)) {
162
162
  rb_raise(rb_eRuntimeError, "compress error error code: %s", ZSTD_getErrorName(ret));
163
163
  }
@@ -104,7 +104,7 @@ rb_streaming_decompress_decompress(VALUE obj, VALUE src)
104
104
  VALUE result = rb_str_new(0, 0);
105
105
  while (input.pos < input.size) {
106
106
  ZSTD_outBuffer output = { (void*)output_data, sd->buf_size, 0 };
107
- size_t const ret = ZSTD_decompressStream(sd->dctx, &output, &input);
107
+ size_t const ret = zstd_decompress(sd->dctx, &output, &input, false);
108
108
  if (ZSTD_isError(ret)) {
109
109
  rb_raise(rb_eRuntimeError, "decompress error error code: %s", ZSTD_getErrorName(ret));
110
110
  }
@@ -26,12 +26,13 @@ static VALUE rb_compress(int argc, VALUE *argv, VALUE self)
26
26
  char* input_data = RSTRING_PTR(input_value);
27
27
  size_t input_size = RSTRING_LEN(input_value);
28
28
  ZSTD_inBuffer input = { input_data, input_size, 0 };
29
+ // ZSTD_compressBound causes SEGV under multi-thread
29
30
  size_t max_compressed_size = ZSTD_compressBound(input_size);
30
31
  VALUE buf = rb_str_new(NULL, max_compressed_size);
31
32
  char* output_data = RSTRING_PTR(buf);
32
33
  ZSTD_outBuffer output = { (void*)output_data, max_compressed_size, 0 };
33
34
 
34
- size_t const ret = zstd_compress(ctx, &output, &input, ZSTD_e_end);
35
+ size_t const ret = zstd_compress(ctx, &output, &input, ZSTD_e_end, true);
35
36
  if (ZSTD_isError(ret)) {
36
37
  ZSTD_freeCCtx(ctx);
37
38
  rb_raise(rb_eRuntimeError, "%s: %s", "compress failed", ZSTD_getErrorName(ret));
@@ -87,19 +88,8 @@ static VALUE rb_compress_using_dict(int argc, VALUE *argv, VALUE self)
87
88
  }
88
89
 
89
90
 
90
- static VALUE decompress_buffered(const char* input_data, size_t input_size)
91
+ static VALUE decompress_buffered(ZSTD_DCtx* dctx, const char* input_data, size_t input_size)
91
92
  {
92
- ZSTD_DStream* const dstream = ZSTD_createDStream();
93
- if (dstream == NULL) {
94
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDStream failed");
95
- }
96
-
97
- size_t initResult = ZSTD_initDStream(dstream);
98
- if (ZSTD_isError(initResult)) {
99
- ZSTD_freeDStream(dstream);
100
- rb_raise(rb_eRuntimeError, "%s: %s", "ZSTD_initDStream failed", ZSTD_getErrorName(initResult));
101
- }
102
-
103
93
  VALUE output_string = rb_str_new(NULL, 0);
104
94
  ZSTD_outBuffer output = { NULL, 0, 0 };
105
95
 
@@ -109,15 +99,14 @@ static VALUE decompress_buffered(const char* input_data, size_t input_size)
109
99
  rb_str_resize(output_string, output.size);
110
100
  output.dst = RSTRING_PTR(output_string);
111
101
 
112
- size_t readHint = ZSTD_decompressStream(dstream, &output, &input);
113
- if (ZSTD_isError(readHint)) {
114
- ZSTD_freeDStream(dstream);
115
- rb_raise(rb_eRuntimeError, "%s: %s", "ZSTD_decompressStream failed", ZSTD_getErrorName(readHint));
102
+ size_t ret = zstd_decompress(dctx, &output, &input, true);
103
+ if (ZSTD_isError(ret)) {
104
+ ZSTD_freeDCtx(dctx);
105
+ rb_raise(rb_eRuntimeError, "%s: %s", "ZSTD_decompressStream failed", ZSTD_getErrorName(ret));
116
106
  }
117
107
  }
118
-
119
- ZSTD_freeDStream(dstream);
120
108
  rb_str_resize(output_string, output.pos);
109
+ ZSTD_freeDCtx(dctx);
121
110
  return output_string;
122
111
  }
123
112
 
@@ -129,6 +118,11 @@ static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
129
118
  StringValue(input_value);
130
119
  char* input_data = RSTRING_PTR(input_value);
131
120
  size_t input_size = RSTRING_LEN(input_value);
121
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx();
122
+ if (dctx == NULL) {
123
+ rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
124
+ }
125
+ set_decompress_params(dctx, kwargs);
132
126
 
133
127
  unsigned long long const uncompressed_size = ZSTD_getFrameContentSize(input_data, input_size);
134
128
  if (uncompressed_size == ZSTD_CONTENTSIZE_ERROR) {
@@ -137,15 +131,9 @@ static VALUE rb_decompress(int argc, VALUE *argv, VALUE self)
137
131
  // ZSTD_decompressStream may be called multiple times when ZSTD_CONTENTSIZE_UNKNOWN, causing slowness.
138
132
  // Therefore, we will not standardize on ZSTD_decompressStream
139
133
  if (uncompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
140
- return decompress_buffered(input_data, input_size);
134
+ return decompress_buffered(dctx, input_data, input_size);
141
135
  }
142
136
 
143
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
144
- if (dctx == NULL) {
145
- rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
146
- }
147
- set_decompress_params(dctx, kwargs);
148
-
149
137
  VALUE output = rb_str_new(NULL, uncompressed_size);
150
138
  char* output_data = RSTRING_PTR(output);
151
139
 
@@ -167,15 +155,6 @@ static VALUE rb_decompress_using_dict(int argc, VALUE *argv, VALUE self)
167
155
  StringValue(input_value);
168
156
  char* input_data = RSTRING_PTR(input_value);
169
157
  size_t input_size = RSTRING_LEN(input_value);
170
- unsigned long long const uncompressed_size = ZSTD_getFrameContentSize(input_data, input_size);
171
- if (uncompressed_size == ZSTD_CONTENTSIZE_ERROR) {
172
- rb_raise(rb_eRuntimeError, "%s: %s", "not compressed by zstd", ZSTD_getErrorName(uncompressed_size));
173
- }
174
- if (uncompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
175
- return decompress_buffered(input_data, input_size);
176
- }
177
- VALUE output = rb_str_new(NULL, uncompressed_size);
178
- char* output_data = RSTRING_PTR(output);
179
158
 
180
159
  char* dict_buffer = RSTRING_PTR(dict);
181
160
  size_t dict_size = RSTRING_LEN(dict);
@@ -183,12 +162,11 @@ static VALUE rb_decompress_using_dict(int argc, VALUE *argv, VALUE self)
183
162
  if (ddict == NULL) {
184
163
  rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDDict failed");
185
164
  }
186
-
187
165
  unsigned const expected_dict_id = ZSTD_getDictID_fromDDict(ddict);
188
166
  unsigned const actual_dict_id = ZSTD_getDictID_fromFrame(input_data, input_size);
189
167
  if (expected_dict_id != actual_dict_id) {
190
168
  ZSTD_freeDDict(ddict);
191
- rb_raise(rb_eRuntimeError, "%s: %s", "DictID mismatch", ZSTD_getErrorName(uncompressed_size));
169
+ rb_raise(rb_eRuntimeError, "DictID mismatch");
192
170
  }
193
171
 
194
172
  ZSTD_DCtx* const ctx = ZSTD_createDCtx();
@@ -196,6 +174,19 @@ static VALUE rb_decompress_using_dict(int argc, VALUE *argv, VALUE self)
196
174
  ZSTD_freeDDict(ddict);
197
175
  rb_raise(rb_eRuntimeError, "%s", "ZSTD_createDCtx failed");
198
176
  }
177
+
178
+ unsigned long long const uncompressed_size = ZSTD_getFrameContentSize(input_data, input_size);
179
+ if (uncompressed_size == ZSTD_CONTENTSIZE_ERROR) {
180
+ ZSTD_freeDDict(ddict);
181
+ ZSTD_freeDCtx(ctx);
182
+ rb_raise(rb_eRuntimeError, "%s: %s", "not compressed by zstd", ZSTD_getErrorName(uncompressed_size));
183
+ }
184
+ if (uncompressed_size == ZSTD_CONTENTSIZE_UNKNOWN) {
185
+ return decompress_buffered(ctx, input_data, input_size);
186
+ }
187
+
188
+ VALUE output = rb_str_new(NULL, uncompressed_size);
189
+ char* output_data = RSTRING_PTR(output);
199
190
  size_t const decompress_size = ZSTD_decompress_usingDDict(ctx, output_data, uncompressed_size, input_data, input_size, ddict);
200
191
  if (ZSTD_isError(decompress_size)) {
201
192
  ZSTD_freeDDict(ddict);
@@ -1,3 +1,3 @@
1
1
  module Zstd
2
- VERSION = "1.5.6.2"
2
+ VERSION = "1.5.6.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zstd-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.6.2
4
+ version: 1.5.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - SpringMT
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-11 00:00:00.000000000 Z
11
+ date: 2024-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler