ruby-zstds 1.0.3 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e2279b518a90a526dd82247626f5969d01f6786de10b91802c5b6b7f3391ac26
4
- data.tar.gz: 854b6e8d08c7cc2fa464e3acc25cf45ea6ff204809b5b2cb08cea94217e34b1f
3
+ metadata.gz: 882ef3555df6569fdb51a8689d2e7b8e710255f98a08a631e023ae0160d3ad86
4
+ data.tar.gz: 233e455b9819cab316812fd7c977735972ad5ff2eeee1a816c329e7a5b7661f1
5
5
  SHA512:
6
- metadata.gz: 68781c24292733752c2e59022d71c31d15d73e73f7b5297374e720fc88e06100e1513772304b7591f16652bfef38b4991b9128949355fd0746bbae9d671eff67
7
- data.tar.gz: dab52302d4ce11b2392d7578fd824c4e4b725c3a7d7c853454d05b7291eeb7a93b024fce8c8d475ea965202bb7795db9a3d59764a5aea012fea49d712a59ae4e
6
+ metadata.gz: 69ce6c1b92687ca88e87619a3314acf3b8c0584c56a1694730e5e5bf7139d5db3c7c280f01df79e1fb010a3c61c0c46af76a82bb1f4815b481421fb7b885f3d4
7
+ data.tar.gz: b77df0f6f9b98523ca3e611bbab7d5655a94c7e637fc61511096da614cb95672fab113894de375f6f406015aebc6eded0d0dabb5025644891775bec8a04cadda
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # Ruby bindings for zstd library
2
2
 
3
- | Travis | AppVeyor | Cirrus | Circle | Codecov |
4
- | :---: | :---: | :---: | :---: | :---: |
5
- | [![Travis test status](https://travis-ci.com/andrew-aladev/ruby-zstds.svg?branch=master)](https://travis-ci.com/andrew-aladev/ruby-zstds) | [![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-zstds?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-zstds/branch/master) | [![Cirrus test status](https://api.cirrus-ci.com/github/andrew-aladev/ruby-zstds.svg?branch=master)](https://cirrus-ci.com/github/andrew-aladev/ruby-zstds) | [![Circle test status](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master) | [![Codecov](https://codecov.io/gh/andrew-aladev/ruby-zstds/branch/master/graph/badge.svg)](https://codecov.io/gh/andrew-aladev/ruby-zstds) |
3
+ | AppVeyor | Circle | Github actions | Codecov | Gem |
4
+ | :------: | :----: | :------------: | :-----: | :--: |
5
+ | [![AppVeyor test status](https://ci.appveyor.com/api/projects/status/github/andrew-aladev/ruby-zstds?branch=master&svg=true)](https://ci.appveyor.com/project/andrew-aladev/ruby-zstds/branch/master) | [![Circle test status](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master.svg?style=shield)](https://circleci.com/gh/andrew-aladev/ruby-zstds/tree/master) | [![Github Actions test status](https://github.com/andrew-aladev/ruby-zstds/workflows/test/badge.svg?branch=master)](https://github.com/andrew-aladev/ruby-zstds/actions) | [![Codecov](https://codecov.io/gh/andrew-aladev/ruby-zstds/branch/master/graph/badge.svg)](https://codecov.io/gh/andrew-aladev/ruby-zstds) | [![Gem](https://img.shields.io/gem/v/ruby-zstds.svg)](https://rubygems.org/gems/ruby-zstds) |
6
6
 
7
7
  See [zstd library](https://github.com/facebook/zstd).
8
8
 
9
9
  ## Installation
10
10
 
11
- Please install zstd library first, use latest 1.4.3+ version.
11
+ Please install zstd library first, use latest 1.4.0+ version.
12
12
 
13
13
  ```sh
14
14
  gem install ruby-zstds
@@ -21,6 +21,8 @@ rake gem
21
21
  gem install pkg/ruby-zstds-*.gem
22
22
  ```
23
23
 
24
+ You can also use [overlay](https://github.com/andrew-aladev/overlay) for gentoo.
25
+
24
26
  ## Usage
25
27
 
26
28
  There are simple APIs: `String` and `File`. Also you can use generic streaming API: `Stream::Writer` and `Stream::Reader`.
@@ -36,6 +38,27 @@ ZSTDS::File.decompress "file.txt.zst", "file.txt"
36
38
 
37
39
  ZSTDS::Stream::Writer.open("file.txt.zst") { |writer| writer << "sample string" }
38
40
  puts ZSTDS::Stream::Reader.open("file.txt.zst") { |reader| reader.read }
41
+
42
+ writer = ZSTDS::Stream::Writer.new output_socket
43
+ begin
44
+ bytes_written = writer.write_nonblock "sample string"
45
+ # handle "bytes_written"
46
+ rescue IO::WaitWritable
47
+ # handle wait
48
+ ensure
49
+ writer.close
50
+ end
51
+
52
+ reader = ZSTDS::Stream::Reader.new input_socket
53
+ begin
54
+ puts reader.read_nonblock(512)
55
+ rescue IO::WaitReadable
56
+ # handle wait
57
+ rescue ::EOFError
58
+ # handle eof
59
+ ensure
60
+ reader.close
61
+ end
39
62
  ```
40
63
 
41
64
  You can create dictionary using `ZSTDS::Dictionary`.
@@ -47,16 +70,16 @@ require "zstds"
47
70
  samples = (Array.new(8) { ::SecureRandom.random_bytes(1 << 8) } + ["sample string"]).shuffle
48
71
 
49
72
  dictionary = ZSTDS::Dictionary.train samples
50
- File.write "dictionary.bin", dictionary.buffer
73
+ File.write "dictionary.bin", dictionary.buffer, :mode => "wb"
51
74
 
52
- dictionary_buffer = File.read "dictionary.bin"
75
+ dictionary_buffer = File.read "dictionary.bin", :mode => "rb"
53
76
  dictionary = ZSTDS::Dictionary.new dictionary_buffer
54
77
 
55
78
  data = ZSTDS::String.compress "sample string", :dictionary => dictionary
56
79
  puts ZSTDS::String.decompress(data, :dictionary => dictionary)
57
80
  ```
58
81
 
59
- You can create and read `tar.zst` archives with `minitar` for example.
82
+ You can create and read `tar.zst` archives with [minitar](https://github.com/halostatue/minitar).
60
83
 
61
84
  ```ruby
62
85
  require "zstds"
@@ -78,160 +101,96 @@ ZSTDS::Stream::Reader.open "file.tar.zst" do |reader|
78
101
  end
79
102
  ```
80
103
 
81
- ## Options
82
-
83
- Each API supports several options:
84
-
85
- ```
86
- :source_buffer_length
87
- :destination_buffer_length
88
- ```
89
-
90
- There are internal buffers for compressed and decompressed data.
91
- For example you want to use 1 KB as source buffer length for compressor - please use 256 B as destination buffer length.
92
- You want to use 256 B as source buffer length for decompressor - please use 1 KB as destination buffer length.
93
-
94
- Values: 0 - infinity, default value: 0.
95
- 0 means automatic buffer length selection.
96
-
97
- ```
98
- :compression_level
99
- ```
100
-
101
- Values: `ZSTDS::Option::MIN_COMPRESSION_LEVEL` - `ZSTDS::Option::MAX_COMPRESSION_LEVEL`, default value: `0`.
102
-
103
- ```
104
- :window_log
105
- ```
106
-
107
- Values: `ZSTDS::Option::MIN_WINDOW_LOG` - `ZSTDS::Option::MAX_WINDOW_LOG`, default value: `0`.
108
-
109
- ```
110
- :hash_log
111
- ```
112
-
113
- Values: `ZSTDS::Option::MIN_HASH_LOG` - `ZSTDS::Option::MAX_HASH_LOG`, default value: `0`.
114
-
115
- ```
116
- :chain_log
117
- ```
118
-
119
- Values: `ZSTDS::Option::MIN_CHAIN_LOG` - `ZSTDS::Option::MAX_CHAIN_LOG`, default value: `0`.
120
-
121
- ```
122
- :search_log
123
- ```
124
-
125
- Values: `ZSTDS::Option::MIN_SEARCH_LOG` - `ZSTDS::Option::MAX_SEARCH_LOG`, default value: `0`.
126
-
127
- ```
128
- :min_match
129
- ```
130
-
131
- Values: `ZSTDS::Option::MIN_MIN_MATCH` - `ZSTDS::Option::MAX_MIN_MATCH`, default value: `0`.
132
-
133
- ```
134
- :target_length
135
- ```
136
-
137
- Values: `ZSTDS::Option::MIN_TARGET_LENGTH` - `ZSTDS::Option::MAX_TARGET_LENGTH`, default value: `0`.
138
-
139
- ```
140
- :strategy
141
- ```
142
-
143
- Values: `ZSTDS::Option::STRATEGIES`, default value: none.
144
-
145
- ```
146
- :enable_long_distance_matching
147
- ```
148
-
149
- Values: true/false, default value: none.
150
-
151
- ```
152
- :ldm_hash_log
153
- ```
154
-
155
- Values: `ZSTDS::Option::MIN_LDM_HASH_LOG` - `ZSTDS::Option::MAX_LDM_HASH_LOG`, default value: `0`.
156
-
157
- ```
158
- :ldm_min_match
159
- ```
160
-
161
- Values: `ZSTDS::Option::MIN_LDM_MIN_MATCH` - `ZSTDS::Option::MAX_LDM_MIN_MATCH`, default value: `0`.
162
-
163
- ```
164
- :ldm_bucket_size_log
165
- ```
166
-
167
- Values: `ZSTDS::Option::MIN_LDM_BUCKET_SIZE_LOG` - `ZSTDS::Option::MAX_LDM_BUCKET_SIZE_LOG`, default value: `0`.
104
+ You can also use `Content-Encoding: zstd` with [sinatra](http://sinatrarb.com):
168
105
 
169
- ```
170
- :ldm_hash_rate_log
171
- ```
172
-
173
- Values: `ZSTDS::Option::MIN_LDM_HASH_RATE_LOG` - `ZSTDS::Option::MAX_LDM_HASH_RATE_LOG`, default value: `0`.
174
-
175
- ```
176
- :content_size_flag
177
- ```
178
-
179
- Values: true/false, default value: true.
180
-
181
- ```
182
- :checksum_flag
183
- ```
184
-
185
- Values: true/false, default value: false.
186
-
187
- ```
188
- :dict_id_flag
189
- ```
190
-
191
- Values: true/false, default value: true.
192
-
193
- ```
194
- :nb_workers
195
- ```
196
-
197
- Values: `ZSTDS::Option::MIN_NB_WORKERS` - `ZSTDS::Option::MAX_NB_WORKERS`, default value: `0`.
106
+ ```ruby
107
+ require "zstds"
108
+ require "sinatra"
198
109
 
199
- ```
200
- :job_size
110
+ get "/" do
111
+ headers["Content-Encoding"] = "zstd"
112
+ ZSTDS::String.compress "sample string"
113
+ end
201
114
  ```
202
115
 
203
- Values: `ZSTDS::Option::MIN_JOB_SIZE` - `ZSTDS::Option::MAX_JOB_SIZE`, default value: `0`.
204
-
205
- ```
206
- :overlap_log
207
- ```
116
+ All functionality (including streaming) can be used inside multiple threads with [parallel](https://github.com/grosser/parallel).
117
+ This code will provide heavy load for your CPU.
208
118
 
209
- Values: `ZSTDS::Option::MIN_OVERLAP_LOG` - `ZSTDS::Option::MAX_OVERLAP_LOG`, default value: `0`.
119
+ ```ruby
120
+ require "zstds"
121
+ require "parallel"
210
122
 
211
- ```
212
- :window_log_max
123
+ Parallel.each large_datas do |large_data|
124
+ ZSTDS::String.compress large_data
125
+ end
213
126
  ```
214
127
 
215
- Values: `ZSTDS::Option::MIN_WINDOW_LOG_MAX` - `ZSTDS::Option::MAX_WINDOW_LOG_MAX`, default value: `0`.
128
+ ## Options
216
129
 
217
- ```
218
- :dictionary
219
- ```
130
+ | Option | Values | Default | Description |
131
+ |---------------------------------|----------------|------------|-------------|
132
+ | `source_buffer_length` | 0 - inf | 0 (auto) | internal buffer length for source data |
133
+ | `destination_buffer_length` | 0 - inf | 0 (auto) | internal buffer length for description data |
134
+ | `gvl` | true/false | false | enables global VM lock where possible |
135
+ | `compression_level` | -131072 - 22 | 0 (auto) | compression level |
136
+ | `window_log` | 10 - 31 | 0 (auto) | maximum back-reference distance (power of 2) |
137
+ | `hash_log` | 6 - 30 | 0 (auto) | size of the initial probe table (power of 2) |
138
+ | `chain_log` | 6 - 30 | 0 (auto) | size of the multi-probe search table (power of 2) |
139
+ | `search_log` | 1 - 30 | 0 (auto) | number of search attempts (power of 2) |
140
+ | `min_match` | 3 - 7 | 0 (auto) | minimum size of searched matches |
141
+ | `target_length` | 0 - 131072 | 0 (auto) | distance between match sampling (for `:fast` strategy), length of match considered "good enough" for (for other strategies) |
142
+ | `strategy` | `STRATEGIES` | nil (auto) | choses strategy |
143
+ | `enable_long_distance_matching` | true/false | nil (auto) | enables long distance matching |
144
+ | `ldm_hash_log` | 6 - 30 | 0 (auto) | size of the table for long distance matching (power of 2) |
145
+ | `ldm_min_match` | 4 - 4096 | 0 (auto) | minimum match size for long distance matcher |
146
+ | `ldm_bucket_size_log` | 1 - 8 | 0 (auto) | log size of each bucket in the LDM hash table for collision resolution |
147
+ | `ldm_hash_rate_log` | 0 - 25 | 0 (auto) | frequency of inserting/looking up entries into the LDM hash table |
148
+ | `content_size_flag` | true/false | true | enables writing of content size into frame header (if known) |
149
+ | `checksum_flag` | true/false | false | enables writing of 32-bits checksum of content at end of frame |
150
+ | `dict_id_flag` | true/false | true | enables writing of dictionary id into frame header |
151
+ | `nb_workers` | 0 - 200 | 0 (auto) | number of threads spawned in parallel |
152
+ | `job_size` | 0 - 1073741824 | 0 (auto) | size of job (nb_workers >= 1) |
153
+ | `overlap_log` | 0 - 9 | 0 (auto) | overlap size, as a fraction of window size |
154
+ | `window_log_max` | 10 - 31 | 0 (auto) | size limit (power of 2) |
155
+ | `dictionary` | `Dictionary` | nil | chose dictionary |
156
+ | `pledged_size` | 0 - inf | 0 (auto) | size of input (if known) |
220
157
 
221
- Special option for dictionary, default value: none.
158
+ There are internal buffers for compressed and decompressed data.
159
+ For example you want to use 1 KB as `source_buffer_length` for compressor - please use 256 B as `destination_buffer_length`.
160
+ You want to use 256 B as `source_buffer_length` for decompressor - please use 1 KB as `destination_buffer_length`.
222
161
 
223
- ```
224
- :pledged_size
225
- ```
162
+ `gvl` is disabled by default, this mode allows running multiple compressors/decompressors in different threads simultaneously.
163
+ Please consider enabling `gvl` if you don't want to launch processors in separate threads.
164
+ If `gvl` is enabled ruby won't waste time on acquiring/releasing VM lock.
226
165
 
227
- Values: 0 - infinity, default value: 0.
228
- It is reasonable to provide size of input (if known) for streaming api.
229
166
  `String` and `File` will set `:pledged_size` automaticaly.
230
167
 
231
- Please read zstd docs for more info about options.
168
+ You can also read zstd docs for more info about options.
169
+
170
+ | Option | Related constants |
171
+ |-----------------------|-------------------|
172
+ | `compression_level` | `ZSTDS::Option::MIN_COMPRESSION_LEVEL` = -131072, `ZSTDS::Option::MAX_COMPRESSION_LEVEL` = 22 |
173
+ | `window_log` | `ZSTDS::Option::MIN_WINDOW_LOG` = 10, `ZSTDS::Option::MAX_WINDOW_LOG` = 31 |
174
+ | `hash_log` | `ZSTDS::Option::MIN_HASH_LOG` = 6, `ZSTDS::Option::MAX_HASH_LOG` = 30 |
175
+ | `chain_log` | `ZSTDS::Option::MIN_CHAIN_LOG` = 6, `ZSTDS::Option::MAX_CHAIN_LOG` = 30 |
176
+ | `search_log` | `ZSTDS::Option::MIN_SEARCH_LOG` = 1, `ZSTDS::Option::MAX_SEARCH_LOG` = 30 |
177
+ | `min_match` | `ZSTDS::Option::MIN_MIN_MATCH` = 3, `ZSTDS::Option::MAX_MIN_MATCH` = 7 |
178
+ | `target_length` | `ZSTDS::Option::MIN_TARGET_LENGTH` = 0, `ZSTDS::Option::MAX_TARGET_LENGTH` = 131072 |
179
+ | `strategy` | `ZSTDS::Option::STRATEGIES` = `%i[fast dfast greedy lazy lazy2 btlazy2 btopt btultra btultra2]` |
180
+ | `ldm_hash_log` | `ZSTDS::Option::MIN_LDM_HASH_LOG` = 6, `ZSTDS::Option::MAX_LDM_HASH_LOG` = 30 |
181
+ | `ldm_min_match` | `ZSTDS::Option::MIN_LDM_MIN_MATCH` = 4, `ZSTDS::Option::MAX_LDM_MIN_MATCH` = 4096 |
182
+ | `ldm_bucket_size_log` | `ZSTDS::Option::MIN_LDM_BUCKET_SIZE_LOG` = 1, `ZSTDS::Option::MAX_LDM_BUCKET_SIZE_LOG` = 8 |
183
+ | `ldm_hash_rate_log` | `ZSTDS::Option::MIN_LDM_HASH_RATE_LOG` = 0, `ZSTDS::Option::MAX_LDM_HASH_RATE_LOG` = 25 |
184
+ | `nb_workers` | `ZSTDS::Option::MIN_NB_WORKERS` = 0, `ZSTDS::Option::MAX_NB_WORKERS` = 200 |
185
+ | `job_size` | `ZSTDS::Option::MIN_JOB_SIZE` = 0, `ZSTDS::Option::MAX_JOB_SIZE` = 1073741824 |
186
+ | `overlap_log` | `ZSTDS::Option::MIN_OVERLAP_LOG` = 0, `ZSTDS::Option::MAX_OVERLAP_LOG` = 9 |
187
+ | `window_log_max` | `ZSTDS::Option::MIN_WINDOW_LOG_MAX` = 10, `ZSTDS::Option::MAX_WINDOW_LOG_MAX` = 31 |
232
188
 
233
189
  Possible compressor options:
234
190
  ```
191
+ :source_buffer_length
192
+ :destination_buffer_length
193
+ :gvl
235
194
  :compression_level
236
195
  :window_log
237
196
  :hash_log
@@ -257,6 +216,9 @@ Possible compressor options:
257
216
 
258
217
  Possible decompressor options:
259
218
  ```
219
+ :source_buffer_length
220
+ :destination_buffer_length
221
+ :gvl
260
222
  :window_log_max
261
223
  :dictionary
262
224
  ```
@@ -270,18 +232,6 @@ data = ZSTDS::String.compress "sample string", :compression_level => 5
270
232
  puts ZSTDS::String.decompress(data, :window_log_max => 11)
271
233
  ```
272
234
 
273
- HTTP encoding (`Content-Encoding: zstd`) using default options:
274
-
275
- ```ruby
276
- require "zstds"
277
- require "sinatra"
278
-
279
- get "/" do
280
- headers["Content-Encoding"] = "zstd"
281
- ZSTDS::String.compress "sample string"
282
- end
283
- ```
284
-
285
235
  ## String
286
236
 
287
237
  String maintains destination buffer only, so it accepts `destination_buffer_length` option only.
@@ -306,7 +256,7 @@ File maintains both source and destination buffers, it accepts both `source_buff
306
256
 
307
257
  ## Stream::Writer
308
258
 
309
- Its behaviour is similar to builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html).
259
+ Its behaviour is similar to builtin [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipWriter.html).
310
260
 
311
261
  Writer maintains destination buffer only, so it accepts `destination_buffer_length` option only.
312
262
 
@@ -344,7 +294,7 @@ Set another encodings, `nil` is just for compatibility with `IO`.
344
294
  #tell
345
295
  ```
346
296
 
347
- See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
297
+ See [`IO`](https://ruby-doc.org/core/IO.html) docs.
348
298
 
349
299
  ```
350
300
  #write(*objects)
@@ -354,7 +304,7 @@ See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
354
304
  #closed?
355
305
  ```
356
306
 
357
- See [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
307
+ See [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
358
308
 
359
309
  ```
360
310
  #write_nonblock(object, *options)
@@ -368,6 +318,9 @@ Special asynchronous methods missing in `Zlib::GzipWriter`.
368
318
  So it is possible to have asynchronous variants for these synchronous methods.
369
319
  Behaviour is the same as `IO#write_nonblock` method.
370
320
 
321
+ All nonblock operations for file will raise `EBADF` error on Windows.
322
+ Setting file into nonblocking mode is [not available on Windows](https://github.com/ruby/ruby/blob/master/win32/win32.c#L4388).
323
+
371
324
  ```
372
325
  #<<(object)
373
326
  #print(*objects)
@@ -376,11 +329,11 @@ Behaviour is the same as `IO#write_nonblock` method.
376
329
  #puts(*objects)
377
330
  ```
378
331
 
379
- Typical helpers, see [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
332
+ Typical helpers, see [`Zlib::GzipWriter`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipWriter.html) docs.
380
333
 
381
334
  ## Stream::Reader
382
335
 
383
- Its behaviour is similar to builtin [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html).
336
+ Its behaviour is similar to builtin [`Zlib::GzipReader`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipReader.html).
384
337
 
385
338
  Reader maintains both source and destination buffers, it accepts both `source_buffer_length` and `destination_buffer_length` options.
386
339
 
@@ -415,7 +368,7 @@ Set another encodings.
415
368
  #tell
416
369
  ```
417
370
 
418
- See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
371
+ See [`IO`](https://ruby-doc.org/core/IO.html) docs.
419
372
 
420
373
  ```
421
374
  #read(bytes_to_read = nil, out_buffer = nil)
@@ -425,14 +378,14 @@ See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
425
378
  #closed?
426
379
  ```
427
380
 
428
- See [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
381
+ See [`Zlib::GzipReader`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
429
382
 
430
383
  ```
431
384
  #readpartial(bytes_to_read = nil, out_buffer = nil)
432
385
  #read_nonblock(bytes_to_read, out_buffer = nil, *options)
433
386
  ```
434
387
 
435
- See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
388
+ See [`IO`](https://ruby-doc.org/core/IO.html) docs.
436
389
 
437
390
  ```
438
391
  #getbyte
@@ -455,7 +408,7 @@ See [`IO`](https://ruby-doc.org/core-2.7.0/IO.html) docs.
455
408
  #ungetline(line)
456
409
  ```
457
410
 
458
- Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib-2.7.0/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
411
+ Typical helpers, see [`Zlib::GzipReader`](https://ruby-doc.org/stdlib/libdoc/zlib/rdoc/Zlib/GzipReader.html) docs.
459
412
 
460
413
  ## Dictionary
461
414
 
@@ -487,14 +440,24 @@ Please use regular constructor to create dictionary from buffer.
487
440
 
488
441
  Read dictionary id from buffer.
489
442
 
443
+ ## Thread safety
444
+
445
+ `:gvl` option is disabled by default, you can use bindings effectively in multiple threads.
446
+ Please be careful: bindings are not thread safe.
447
+ You should lock all shared data between threads.
448
+
449
+ For example: you should not use same compressor/decompressor inside multiple threads.
450
+ Please verify that you are using each processor inside single thread at the same time.
451
+
452
+ ## Operating systems
453
+
454
+ GNU/Linux, FreeBSD, OSX, Windows (MinGW).
455
+
490
456
  ## CI
491
457
 
492
- See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
493
458
  Please visit [scripts/test-images](scripts/test-images).
494
- You can run this test script using many native and cross images.
495
-
496
- Cirrus CI uses `x86_64-pc-linux-gnu` image, Circle CI - `x86_64-gentoo-linux-musl` image.
459
+ See universal test script [scripts/ci_test.sh](scripts/ci_test.sh) for CI.
497
460
 
498
461
  ## License
499
462
 
500
- MIT license, see LICENSE and AUTHORS.
463
+ MIT license, see [LICENSE](LICENSE) and [AUTHORS](AUTHORS).