Parallel random access to gzip files
Project description
Parallel Random Access Gzip (pragzip)
This module provides a PragzipFile class, which can be used to seek inside gzip files without having to decompress them first.
Alternatively, you can use this simply as a parallelized gzip decoder as a replacement for Python's builtin gzip
module in order to fully utilize all your cores.
The random seeking support is the same as provided by indexed_gzip but further speedups are realized at the cost of higher memory usage thanks to a least-recently-used cache in combination with a parallelized prefetcher.
Table of Contents
- Installation
- Usage
- Performance comparison with gzip module
- Internal Architecture
- Tracing the Decoder
Installation
You can simply install it from PyPI:
python3 -m pip install --upgrade pip # Recommended for newer manylinux wheels
python3 -m pip install pragzip
The latest unreleased development version can be tested out with:
python3 -m pip install --force-reinstall 'git+https://github.com/mxmlnkn/indexed_bzip2.git@master#egginfo=pragzip&subdirectory=python/pragzip'
And to build locally, you can use build
and install the wheel:
cd python/pragzip
rm -rf dist
python3 -m build .
python3 -m pip install --force-reinstall --user dist/*.whl
Usage
Command Line Tool
pragzip --help
# Parallel decoding: 1.7 s
time pragzip -d -c -P 0 sample.gz | wc -c
# Serial decoding: 22 s
time gzip -d -c sample.gz | wc -c
Python Library
Simple open, seek, read, and close
from pragzip import PragzipFile
file = PragzipFile( "example.gz", parallelization = os.cpu_count() )
# You can now use it like a normal file
file.seek( 123 )
data = file.read( 100 )
file.close()
The first call to seek will ensure that the block offset list is complete and therefore might create them first. Because of this the first call to seek might take a while.
Use with context manager
import os
import pragzip
with pragzip.open( "example.gz", parallelization = os.cpu_count() ) as file:
file.seek( 123 )
data = file.read( 100 )
Storing and loading the block offset map
The creation of the list of gzip blocks can take a while because it has to decode the gzip file completely. To avoid this setup when opening a gzip file, the block offset list can be exported and imported.
Open a pure Python file-like object for indexed reading
import io
import os
import pragzip as pragzip
with open( "example.gz", 'rb' ) as file:
in_memory_file = io.BytesIO( file.read() )
with pragzip.open( in_memory_file, parallelization = os.cpu_count() ) as file:
file.seek( 123 )
data = file.read( 100 )
Via Ratarmount
Because pragzip
can be used as a backend in ratarmount, you can use ratarmount to mount single gzip files easily.
Furthermore, since ratarmount 0.11.0, parallelization is the default and does not have to be specified explicitly with -P
.
base64 /dev/urandom | head -c $(( 4 * 1024 * 1024 * 1024 )) | gzip > sample.gz
# Serial decoding: 23 s
time gzip -c -d sample.gz | wc -c
python3 -m pip install --user ratarmount
ratarmount sample.gz mounted
# Parallel decoding: 3.5 s
time cat mounted/sample | wc -c
# Random seeking to the middle of the file and reading 1 MiB: 0.287 s
time dd if=mounted/sample bs=$(( 1024 * 1024 )) \
iflag=skip_bytes,count_bytes skip=$(( 2 * 1024 * 1024 * 1024 )) count=$(( 1024 * 1024 )) | wc -c
C++ library
Because it is written in C++, it can of course also be used as a C++ library.
In order to make heavy use of templates and to simplify compiling with Python setuptools
, it is mostly header-only so that integration it into another project should be easy.
The license is also permissive enough for most use cases.
I currently did not yet test integrating it into other projects other than simply manually copying the source in src/core
, src/pragzip
, and if integrated zlib is desired also src/external/zlib
.
If you have suggestions and wishes like support with CMake or Conan, please open an issue.
Performance comparison with gzip module when a gzip index exists
These are simple timing tests for reading all the contents of a gzip file sequentially.
import gzip
import time
with gzip.open( gzipFilePath ) as file:
t0 = time.time()
while file.read( 4*1024*1024 ):
pass
t1 = time.time()
print( f"Decoded file in {t1-t0}s" )
The usage of pragzip is slightly different:
import indexed_gzip
import pragzip
import time
with indexed_gzip.IndexedGzipFile(gzipFilePath) as file:
file.build_full_index()
file.export_index(gzipFilePath + ".index")
# parallelization = 0 means that it is automatically using all available cores.
for parallelization in [0, 1, 2, 6, 12, 24, 32]:
with pragzip.PragzipFile(gzipFilePath, parallelization = parallelization) as file:
file.set_block_offsets(open(gzipFilePath + ".index", 'rb'))
t0 = time.time()
while file.read( 4*1024*1024 ):
pass
t1 = time.time()
print( f"Decoded file in {t1-t0}s" )
Results for an AMD Ryzen 3900X 12-core (24 virtual cores) processor and with gzipFilePath=4GB-base64.gz
, which is a 4 GiB gzip compressed file with base64 random data.
Module | Runtime / s |
---|---|
gzip | 17.2 |
pragzip with parallelization = 0 | 1.25 |
pragzip with parallelization = 1 | 13.8 |
pragzip with parallelization = 2 | 7.0 |
pragzip with parallelization = 6 | 2.5 |
pragzip with parallelization = 12 | 1.47 |
pragzip with parallelization = 24 | 1.25 |
pragzip with parallelization = 32 | 1.33 |
The speedup of pragzip
over the gzip
module with parallelization = 0
is 17.2/1.25 = 14.
When using only one core, pragzip
is faster by (17.2-13.8)/17.2 = 20%.
Internal Architecture
The main part of the internal architecture used for parallelizing is the same as used for indexed_bzip2.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for pragzip-0.2.2-pp39-pypy39_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 767c3cd62dcb7fc15f7a45bbbb8e72d8d3b859e8e324e25697c52c1abfefb291 |
|
MD5 | 2f32fb9202f6efdd37c3585519b3e7c1 |
|
BLAKE2b-256 | 05a4ff0f869d7b7c7381ccf6b272f9d84cef5e30a9e90a19a4971bd0fb6f29f0 |
Hashes for pragzip-0.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fed88b5f1d59d62bd3aff01e59615240d8cd79cefdc7cb1cb018b9bf1cb1dfed |
|
MD5 | 7c2b1134cd144d2dea562cff355cd734 |
|
BLAKE2b-256 | 4c9e1d1199ef60b6a8cb142cccc4034d47fdb2d8913a6e5ea5950d65cd69266f |
Hashes for pragzip-0.2.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6aeb564b10e6d0f05485b65a1db861b65a49dee1b4f02a09a1a0f2d4e8e32a1e |
|
MD5 | 267981c550949eb785f6b60fdd918da4 |
|
BLAKE2b-256 | bb7483d0b1b4558c1d1db08b914a91f9e4880cdf582bdc816d592652c5d3158e |
Hashes for pragzip-0.2.2-pp38-pypy38_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 00407f2fcb788a0a0a5ad706ff0e04a7bda74caf94670c580f91db65e0ccad4a |
|
MD5 | f4b59c8e83a78ce9c989d2420095a16e |
|
BLAKE2b-256 | 72de239289e62578adfa4282938e9a53f9b19df151ef7211f5a8d3e0edd533e4 |
Hashes for pragzip-0.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c74eac7f3a0fc21e0d010a6fc56c10e17c353d2da45eb651f217bfc23cc84122 |
|
MD5 | 559ec7ac2e05e2517997f9710bbafb62 |
|
BLAKE2b-256 | 4f80bca27adf18994163db134bac0fd339cdf085904f8039d9630f1931fbbf96 |
Hashes for pragzip-0.2.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4d8c369cc6ec1af3a530f65517ee46f1cb80d42a9e5d1cd4dfee6073d16139b8 |
|
MD5 | f24c6478db857074919cf5714e988667 |
|
BLAKE2b-256 | d4c32eba584ade2ddf0b2200b39a0605b099fee32f324372ade342f42b4c21ff |
Hashes for pragzip-0.2.2-pp37-pypy37_pp73-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1b1d55b459104e46fd1c0965e14f247938baa4a23340701a877f8ca8acc05643 |
|
MD5 | 82d5079659d24ca68f9ee222d506131b |
|
BLAKE2b-256 | c3b527862aa5632a770d38293623816dfd4323b9894386add7f81dd508ef35bd |
Hashes for pragzip-0.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d05c61cf856266b50747b15dc414ee51a96e963094870c2af0485e77e70a4eff |
|
MD5 | 0de677c46e6702d34d271ad0676638c0 |
|
BLAKE2b-256 | 2e667db8afeb4992ef4f21998cc053ce7058c1bee1b144a91ace26bc4a655836 |
Hashes for pragzip-0.2.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 39adfe228ae74a3457ff9d4827776bd1e35dc22d50705535ecb96cf6167f0672 |
|
MD5 | 3045422b9bbe62173f4624a80c91461b |
|
BLAKE2b-256 | d4a1586c6d1fdbdaabe4dd53eb8f5f7d5d6d453ca9c3d411946458c62a847fbd |
Hashes for pragzip-0.2.2-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1bd223c481d7139f373515ceecce8ad5772d2e3c2178e2556abe2dc2c994dcdd |
|
MD5 | c580f4c9471d9195f083708207724bf0 |
|
BLAKE2b-256 | 67c8df79d3977280d1887a6a7880c1c294bff6bba11dee1dbefb622a45eb6068 |
Hashes for pragzip-0.2.2-cp310-cp310-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d21c8b20ee2c03bcb8abb710adc43ebf2e38bdc122195944330f30ad7500caf3 |
|
MD5 | bf1b51c471dd32fa58e0623d379482dc |
|
BLAKE2b-256 | 333bb84f581b635bf473e4695aa9a660de2f7d8d8d3c87557720ee22fccf5043 |
Hashes for pragzip-0.2.2-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5b0b12487b87a551663c82367bc2b1d7d0f493d0b892505c455734704fa5523e |
|
MD5 | b27d1aef261ca0b189d0dc0208032dcd |
|
BLAKE2b-256 | 66b589b3261effbf370bafa5ce8d33b37fdfd6545876894c9bab75bba84ccf5c |
Hashes for pragzip-0.2.2-cp310-cp310-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 547f77e328249326231c83dc2ca1f9a6dea710fd770e24ee789cdb684615dc54 |
|
MD5 | aa22e340f495763da80fbc17e78ed98c |
|
BLAKE2b-256 | 1e9520f70244acb34b855c5b27f98cf2879d88814e49828210dcc9d7158a5b47 |
Hashes for pragzip-0.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a6b34cdd01b44c2d1f8ca18f286d573867b1ad0237ac41b7d576c0f0da7423af |
|
MD5 | c67dae914e5265207e782851b30b0511 |
|
BLAKE2b-256 | acdebcafd5cb923a688dc9d10caa6fa167d744c3a9a3b134f03b8aa2f84040b3 |
Hashes for pragzip-0.2.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5836967619d6c6a0a9481cb88c2db73c487464a52b84e2f594e33fe2a90c9bf7 |
|
MD5 | 83bb3ba70f34dcd7dc7a3c98494a8194 |
|
BLAKE2b-256 | 93678000c32b0751ef07359a0b297b726bcfeeaabb7ccca42c34cdebde86cf1e |
Hashes for pragzip-0.2.2-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 534def5c1b1e70659f3bcdf6d3902a76fd8307d09239e238f9214d34b3ad9c44 |
|
MD5 | d6f1f0c496bfdf5c74b5cc0aca0bc8a9 |
|
BLAKE2b-256 | 2b697a23e69d58a61ffbbaa83242cc6c5629848dfa5d193bfd60524fca9c637a |
Hashes for pragzip-0.2.2-cp39-cp39-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9058c93d79ab008c31f12047883e4c697d091fecb139ee1e0752fce2b3d977a1 |
|
MD5 | 38ff01b1b68c86bb052fd4b3853e713b |
|
BLAKE2b-256 | f94f79da5572f659530de5f73833e0ea1fce6d7feb439a0a3796082b2c2bb1a9 |
Hashes for pragzip-0.2.2-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a68bf58410c856b8780c5154cbda6eb18a20612f534f30b4345e2000a5713c09 |
|
MD5 | 09edcf6ed8c28db927b70b23c1466137 |
|
BLAKE2b-256 | 5d37831c760483d45e292bbac2b3162dff75fbda6b087ef765530f8d31b5cf41 |
Hashes for pragzip-0.2.2-cp39-cp39-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 077af69b7af0dcfcb5977e9f872be1312349e1080bc9ff326e2b150c53d8d4ed |
|
MD5 | 018ab0612543e075f1aa1be68a833691 |
|
BLAKE2b-256 | e90ffd2d650e45043b80b41a6cbb89be6dd0c21cddc142f8a8af7e1c41b48bcb |
Hashes for pragzip-0.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d405b4d0c803020fdf97b7eb14a96e41c8230806a0034aee5a78bb358a362971 |
|
MD5 | c6468d9bf2da223527c6de02b69ea9af |
|
BLAKE2b-256 | 046aa5dac8beecc4c05be203ce2dae333c574f87598e846e8e5d09a190f00d7c |
Hashes for pragzip-0.2.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 89df40ffd3cb8eb6283a5854936f4b4c3c44670bf8a0e47295173dd2297dc8b6 |
|
MD5 | 5221ce633a2d234b4b753396f483dc8c |
|
BLAKE2b-256 | bca9a93f2d92080fcfefb2ed8a06aada3ab755576896b053f0152c1dd2b9571f |
Hashes for pragzip-0.2.2-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 40cd77f316a30293eeb4c46ad70a7fb826d94136918d08befa6e37a883bf05ba |
|
MD5 | d593e536acb177fb299b499f0a1c511b |
|
BLAKE2b-256 | 27c59e50f7e6ad7f50476feaf28f1a9632505ddc6850bbf00643f11af46c99d7 |
Hashes for pragzip-0.2.2-cp38-cp38-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 245d856bbb81d54a26a1783ebca673f9f539dade13c232f4e136766c60e186ec |
|
MD5 | a43f3118a550f09bbd9ed513c9d24438 |
|
BLAKE2b-256 | fc959fe133797fd37ab675216f50b135c2339969d82ed6d9bdb6c5e560f11e33 |
Hashes for pragzip-0.2.2-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 12228b260fbf2b20db3463031fe3f98084985d9ac7fe36aee1b246a50415fa20 |
|
MD5 | 0e4ded270226f47498e528e73ce63693 |
|
BLAKE2b-256 | c1104c9f1dca9779be361b78b1c10c28e1cd682311717d683516dcde41b9867f |
Hashes for pragzip-0.2.2-cp38-cp38-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3d8ed1a7486b6baa7df03b1f4c49000c424aaa7d279655bf0b08eb0613404e0d |
|
MD5 | e27db7fb66123f747ad85c565bdb20fc |
|
BLAKE2b-256 | d0cd2669d7777e261d9fd035582828f56b91c23757d56c8f2839c434aca5c9bf |
Hashes for pragzip-0.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d3412f0ae6009819bbad32738db8ac317d8f19f482a55b9a6a708c2aba9c5a95 |
|
MD5 | 43c5aab0289f3eda158054aa9113b1ea |
|
BLAKE2b-256 | fe4159d416277b11ce3d18495e7f58bb03f9d2a70411b70943d4ddbe379a0f22 |
Hashes for pragzip-0.2.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7ef4fb4d26ad904ebbdaa5a074af1b7d8303d10b8707160290415e5b04b06b39 |
|
MD5 | 2557f7c030e0860598b5522263fbddf8 |
|
BLAKE2b-256 | d14371846d65dba13ecd26b49eb97b26463a3830be2df9250c304aa0f09161f2 |
Hashes for pragzip-0.2.2-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fc8156da05eb59a095ca6b7bec05cfd098e70b4f64f185de2d38d85f353bc3af |
|
MD5 | a7a51a2ff0ff6d95514de39c15828652 |
|
BLAKE2b-256 | e2d5a6271f8e413b582d096a2bc77bb4e0f777a5d7e3c492e8085aee4afaeb15 |
Hashes for pragzip-0.2.2-cp37-cp37m-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7b6129aeedf3158780c3b8fb9aa2cc2b5714f3ed0aa49d151277efe2c45b5aaa |
|
MD5 | b6d4906c0e9ce5679950be57b07ebf27 |
|
BLAKE2b-256 | d3a3d756c49cbd25b3f4ed7a83c569b878cfc695a2fb9fb8ce43efca0f3cf2f0 |
Hashes for pragzip-0.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9793648756ead647d441202c7ad4648fc6c2f30102712c42b04ad80a9ea0b33c |
|
MD5 | 48c8607299157a249c8399c68f22b65c |
|
BLAKE2b-256 | 970ceecd29cb2196bf9788a6a6c9c532013df7925600b71a9765501e5dc8451a |
Hashes for pragzip-0.2.2-cp37-cp37m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | abdb98b33365ce872516f94f7f049f04ca8e90c1358c450ac08bda5875344bf5 |
|
MD5 | 3adbe407e15820f54135477fa12eb2f3 |
|
BLAKE2b-256 | b9a4c07cb8f34c532a8fed268a92a9ca1b0402df8728b1e23c54d119a11c14b0 |
Hashes for pragzip-0.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | cfe4c02cbed3554cf21f114b6f2a2708c2bddf11a100a859631504fb6a32f59e |
|
MD5 | cd3e47b7d2c817a5ef1557b411d94f66 |
|
BLAKE2b-256 | 7351c65a51b579b01490fede659d473dcec6ef4cecd6efae510dddb51d66d080 |
Hashes for pragzip-0.2.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bb27a082d7e5c9117c931bb74d0a1cf939b821f4e42a68920b3e92c05fc1ec2b |
|
MD5 | a23a6f49a5ac9f4a474dd2de28ae160b |
|
BLAKE2b-256 | 24b0fa723626ab637d0809e73aab2018e273ae8a9c6f04ee91b9230f81ad7e9a |
Hashes for pragzip-0.2.2-cp36-cp36m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 724426a41bd444f59d1c2541e88b638983dfa6370c3a00001a5f0c507c84d0aa |
|
MD5 | 75ede2de5039c5bb5f4b2f608e81be0c |
|
BLAKE2b-256 | 43ba91949af60d42f9f0a466a8d9e9d442f1d3fb315c4254688deb59d231657d |
Hashes for pragzip-0.2.2-cp36-cp36m-win32.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 29ba5e93cad7a486e683fdf97c298d323e415d18ba0c40d3e1156cf6d7a77c11 |
|
MD5 | 50ae7f551272571f4b1d58888835b027 |
|
BLAKE2b-256 | 86c906b1deb24b52af0541ff8c2ef9acc0b3d0a9469db55081b96af9d3416756 |
Hashes for pragzip-0.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fd15442dc3eef73898a7ec3b9a9266b39da8c5d29bfba19deb1520d68dfccd09 |
|
MD5 | 8de88071d6df81c03a80da9994d19b2e |
|
BLAKE2b-256 | c7fe5f6667f7de8ada5732e31a878b55a56bd4b3f9546dc4967ee6affd4a270d |
Hashes for pragzip-0.2.2-cp36-cp36m-musllinux_1_1_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e5f62f21c98a158098964160063f9d337ca6beec9ca6845c49b6cd140d7673c8 |
|
MD5 | f87e6eb6e3636992593254813823cde1 |
|
BLAKE2b-256 | c7b4a7b54b8fbf85caebde83d9a524b5e66074528efc95d1f1e1822ea5752ef2 |
Hashes for pragzip-0.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | aff00ce770f071a569dffb8e67ec9ad72ac421b7e3f45378be33fbcd4f1983b4 |
|
MD5 | 4a272598c5165e2c9c74eb14e41fab9f |
|
BLAKE2b-256 | 47fc8607516019abf6c21475cbd91ada990e53af5fac70de465c43e244ecfeb9 |
Hashes for pragzip-0.2.2-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 89e61c8044f76d6b4a9f51729772db53606d1854834cb82a37a3c427e389ca39 |
|
MD5 | 266e2479f8c97ad2de5e920eadce42e6 |
|
BLAKE2b-256 | c523f1bdacbf3a325c8171014bc3f0abfd705eac3079868a832a779ff0b4c96b |