Crunch multi-gigabyte strings with ease
Project description
StringZilla 🦖
StringZilla is the Godzilla of string libraries, splitting, sorting, and shuffling large textual datasets faster than you can say "Tokyo Tower" 😅
- Python docs
- C docs
- JavaScript docs.
- Rust docs.
Performance
StringZilla uses a heuristic so simple it's almost stupid... but it works.
It matches the first few letters of words with hyper-scalar code to achieve memcpy
speeds.
The implementation fits into a single C 99 header file and uses different SIMD flavors and SWAR on older platforms.
So if you're haunted by open(...).readlines()
and str().splitlines()
taking forever, this should help 😊
Substring Search
Backend \ Device | IoT | Laptop | Server |
---|---|---|---|
Speed Comparison 🐇 | |||
Python for loop |
4 MB/s | 14 MB/s | 11 MB/s |
C++ for loop |
520 MB/s | 1.0 GB/s | 900 MB/s |
C++ string.find |
560 MB/s | 1.2 GB/s | 1.3 GB/s |
Scalar StringZilla | 2 GB/s | 3.3 GB/s | 3.5 GB/s |
Hyper-Scalar StringZilla | 4.3 GB/s | 12 GB/s | 12.1 GB/s |
Efficiency Metrics 📊 | |||
CPU Specs | 8-core ARM, 0.5 W/core | 8-core Intel, 5.6 W/core | 22-core Intel, 6.3 W/core |
Performance/Core | 2.1 - 3.3 GB/s | 11 GB/s | 10.5 GB/s |
Bytes/Joule | 4.2 GB/J | 2 GB/J | 1.6 GB/J |
Partition & Sort
Coming soon.
Quick Start: Python 🐍
- Install via pip:
pip install stringzilla
- Import the classes you need:
from stringzilla import Str, Strs, File
Basic Usage
StringZilla offers two mostly interchangeable core classes:
from stringzilla import Str, File
text_from_str = Str('some-string')
text_from_file = Str(File('some-file.txt'))
The Str
is designed to replace long Python str
strings and wrap our C-level API.
On the other hand, the File
memory-maps a file from persistent memory without loading its copy into RAM.
The contents of that file would remain immutable, and the mapping can be shared by multiple Python processes simultaneously.
A standard dataset pre-processing use case would be to map a sizeable textual dataset like Common Crawl into memory, spawn child processes, and split the job between them.
Basic Operations
- Length:
len(text) -> int
- Indexing:
text[42] -> str
- Slicing:
text[42:46] -> Str
- String conversion:
str(text) -> str
- Substring check:
'substring' in text -> bool
- Hashing:
hash(text) -> int
Advanced Operations
text.contains('substring', start=0, end=9223372036854775807) -> bool
text.find('substring', start=0, end=9223372036854775807) -> int
text.count('substring', start=0, end=9223372036854775807, allowoverlap=False) -> int
text.splitlines(keeplinebreaks=False, separator='\n') -> Strs
text.split(separator=' ', maxsplit=9223372036854775807, keepseparator=False) -> Strs
Collection-Level Operations
Once split into a Strs
object, you can sort, shuffle, and reorganize the slices.
lines: Strs = text.split(separator='\n')
lines.sort()
lines.shuffle(seed=42)
Need copies?
sorted_copy: Strs = lines.sorted()
shuffled_copy: Strs = lines.shuffled(seed=42)
Basic list
-like operations are also supported:
lines.append('Pythonic string')
lines.extend(shuffled_copy)
Low-Level Python API
The StringZilla CPython bindings implement vector-call conventions for faster calls.
import stringzilla as sz
contains: bool = sz.contains("haystack", "needle", start=0, end=9223372036854775807)
offset: int = sz.find("haystack", "needle", start=0, end=9223372036854775807)
count: int = sz.count("haystack", "needle", start=0, end=9223372036854775807, allowoverlap=False)
levenstein: int = sz.levenstein("needle", "nidl")
Quick Start: C 🛠️
There is an ABI-stable C 99 interface, in case you have a database, an operating system, or a runtime you want to integrate with StringZilla.
#include "stringzilla.h"
// Initialize your haystack and needle
sz_string_view_t haystack = {your_text, your_text_length};
sz_string_view_t needle = {your_subtext, your_subtext_length};
// Perform string-level operations
sz_size_t character_count = sz_count_char(haystack.start, haystack.length, "a");
sz_size_t substring_position = sz_find_substring(haystack.start, haystack.length, needle.start, needle.length);
// Hash strings
sz_u32_t crc32 = sz_hash_crc32(haystack.start, haystack.length);
// Perform collection level operations
sz_sequence_t array = {your_order, your_count, your_get_start, your_get_length, your_handle};
sz_sort(&array, &your_config);
Contributing 👾
Future development plans include:
- Replace PyBind11 with CPython
- Bindings for JavaScript
- Faster string sorting algorithm
- Reverse-order operations in Python
- Splitting with multiple separators at once
- Splitting CSV rows into columns
- UTF-8 validation.
- Arm SVE backend
- Bindings for Java and Rust
Here's how to set up your dev environment and run some tests.
Development
CPython:
# Clean up, install, and test!
rm -rf build && pip install -e . && pytest scripts/ -s -x
# Install without dependencies
pip install -e . --no-index --no-deps
NodeJS:
npm install && npm test
Benchmarking
To benchmark on some custom file and pattern combinations:
python scripts/bench.py --haystack_path "your file" --needle "your pattern"
To benchmark on synthetic data:
python scripts/bench.py --haystack_pattern "abcd" --haystack_length 1e9 --needle "abce"
Packaging
To validate packaging:
cibuildwheel --platform linux
Compiling C++ Tests
cmake -B ./build_release -DSTRINGZILLA_BUILD_TEST=1 && make -C ./build_release -j && ./build_release/stringzilla_test
On MacOS it's recommended to use non-default toolchain:
# Install dependencies
brew install libomp llvm
# Compile and run tests
cmake -B ./build_release \
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
-DSTRINGZILLA_USE_OPENMP=1 \
-DSTRINGZILLA_BUILD_TEST=1 \
&& \
make -C ./build_release -j && ./build_release/stringzilla_test
License 📜
Feel free to use the project under Apache 2.0 or the Three-clause BSD license at your preference.
If you like this project, you may also enjoy USearch, UCall, UForm, UStore, SimSIMD, and TenPack 🤗
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 Distributions
Built Distributions
Hashes for stringzilla-2.0.1-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a461f494ca2ba9b52a6bde7a9cd72883c7b9cdece5fb2d7aa89930bec2e8a751 |
|
MD5 | 2a54ab63ab7a7145254d6ccf244cee3c |
|
BLAKE2b-256 | cf813366fbcb22675dd2e98cb81bc90980b7fb02fe9474a44e4ce792d73e94cf |
Hashes for stringzilla-2.0.1-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a7a4057eba45e7cc11ddf6903debd872fede4a091ddf4ee535452d44fda5c692 |
|
MD5 | 754912bd568cfff0851502e14e6eb77b |
|
BLAKE2b-256 | 23e8efb62d096a4a0597a24de030c8575dad24fb98fdfe16a203edcee85be8a1 |
Hashes for stringzilla-2.0.1-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 99c6d62f45bce50990d4e9de2710ff0db59f1a1a7b2641cde4f3592b6e729b15 |
|
MD5 | cb5d2836ed7154d04180308d43a2d66f |
|
BLAKE2b-256 | 2b86bd381b557d6397729f92c3f0a8de154fe7d2df03aef95f8cead8343c1416 |
Hashes for stringzilla-2.0.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a2aebcf13f712f0fb174a2f16e7ac538f2c1b6a907c6b70cae5af2f9bad9bfde |
|
MD5 | 9bde2d3fbb3baa7efa6683f8bda9712f |
|
BLAKE2b-256 | e862e1a212b48a9fb505ca1656a993eacce4ce0a195147316b097269e933f4e5 |
Hashes for stringzilla-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 14209ab900578b979a4f96ef1acca65653287697dc677b67934c7d809137bd37 |
|
MD5 | fab979a7c4158532cf3427f672baa796 |
|
BLAKE2b-256 | 26d1376ea30e3462070ef5965b817c00d3345882543c1271b429c305518fed6f |
Hashes for stringzilla-2.0.1-cp312-cp312-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f4de55f1ea344293e96ef88f475620e5825e08ae9bcb51849bb63a4b43de6039 |
|
MD5 | 81478d3031c1416910dfba0633328721 |
|
BLAKE2b-256 | d6be9239d9b107f1b954a3424e87ff633c4eab6a5fb56e4b98669b661998faa2 |
Hashes for stringzilla-2.0.1-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | d95f0cd4ad9a77b9c72db1610f6e07ae7ee5e2d11856b77367d3e0e82e2bff03 |
|
MD5 | 1f1b0eaab806919c67046ef061fe8735 |
|
BLAKE2b-256 | d89ab238c5ff9e95e2264db1c566c40b201c8e93f6710284124f2f9e29294f70 |
Hashes for stringzilla-2.0.1-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1dbf41d85defcf5538102a1f6136f0b6ab609cc830390890ab1cdea3b40cd4a1 |
|
MD5 | 397ea2b6e6fae63f29d2d601c4937b8d |
|
BLAKE2b-256 | ccc1dac76b74f91947eba23759d4d2e0f649bfb87ac56b8608573d336d676331 |
Hashes for stringzilla-2.0.1-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f68f78c29a5cb79a85a54f30230f46817d8363bf41c361fcd890f33e29166943 |
|
MD5 | 2ddfff08e1123f4c44b1355ec7d390ee |
|
BLAKE2b-256 | 71557b59db6fff2765fe051bc660dce757ed20b1557dcc56cdd0429f8348e7fd |
Hashes for stringzilla-2.0.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e88d306dd565439346ea764b150447348fd0c6b769a0b1a7ebd4a03c0c5cf895 |
|
MD5 | 19189b04a4b484919940366acd246864 |
|
BLAKE2b-256 | b6404bf90b5d263ea873c2a76ef2bd6f99974bbb65b7d6b5639cce00d05b9896 |
Hashes for stringzilla-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ac7fadfa364f384a4b95a033dbd94555d9ce9ce7e7e9045fcd5e7ad896fc7ef7 |
|
MD5 | 47d51c6e25ef4e27e156ff8b5cb90b98 |
|
BLAKE2b-256 | 460cdc664c01359197964d77ad3fb30320412c46eb2331b1eea3431435d42621 |
Hashes for stringzilla-2.0.1-cp311-cp311-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3537b84225c5e7a07e492b1c006121f56322d811e436ea72786c3e2c727eab2d |
|
MD5 | 472ecda63708cbd8500c8e843da87153 |
|
BLAKE2b-256 | 4755023a391cb70b968a6dea17d08366764111619d262aa679786912cea2b0b7 |
Hashes for stringzilla-2.0.1-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b9041b81dccf30c992142bf91b24f79bdc4f84e2051dd6b5f385b96390747208 |
|
MD5 | 4d6c5a1c37a4ce479db343ff3defbba7 |
|
BLAKE2b-256 | 4ee7ec94c1a16298575fe41b4b4bb59a8fffa2091c88dfd4e57b95711f3de855 |
Hashes for stringzilla-2.0.1-cp310-cp310-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9ca606dd285b347132f40ffc7e6252166a9fac66a6dcf2a62fd05e3fb22df445 |
|
MD5 | ce41edce3efea2e3aa57f06c5df6a792 |
|
BLAKE2b-256 | ff196fa64401989e6af835322e25f73ea97cc47d3182d54c4f29af17dd9104fd |
Hashes for stringzilla-2.0.1-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 989b03195e6c0e800f2980231723e4254872d480a6a0ff071310a3b062f1616c |
|
MD5 | 634fae12a21a0a8d5984e02a2e0f67fb |
|
BLAKE2b-256 | f86143f184dc97563dec3e8477a21d15813e8431b26b3aa1fe5b191ce64dfecb |
Hashes for stringzilla-2.0.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 26c3cedc74201767bde672982ec0fd98e115cc4fbc7226369b3432cb73f66af8 |
|
MD5 | 2f3e06bd4536ec1ba504eb35f0875b52 |
|
BLAKE2b-256 | c56e1d4a72421b1706375282aaf062301376821183a665bfbbd34a3699b7ffb8 |
Hashes for stringzilla-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 293368aa8fdae2f67dceaf8e1f1f022d265b8a7894bc0091970d7d80a3621cc3 |
|
MD5 | 5e5a45a3ffc44b95f7690c76e31f6b92 |
|
BLAKE2b-256 | d9d45fb5f3b91f6efa41a5a7dd66a5913b0fd93a14105a054f0f7308d861f394 |
Hashes for stringzilla-2.0.1-cp310-cp310-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1cf189137f07de9e2708db035bd649b676491f7caadde4538fea35f71bdda0f6 |
|
MD5 | d2d8747cdd7af70b51112e9da5f54061 |
|
BLAKE2b-256 | 954c9d82bc31e1920416fe6c0588161c82a377b54461eecb4d6c7cdd4624383c |
Hashes for stringzilla-2.0.1-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a9617f2070e9ce2f3dd44f40cfbaca56221ab27d3665db22685754dd6a451190 |
|
MD5 | 179ff17012ef6dbb654282161b17865e |
|
BLAKE2b-256 | a3441409208f0b14aca7911766ef2b30edc8b9cd14d4a1a248ea778cdd3141b7 |
Hashes for stringzilla-2.0.1-cp39-cp39-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | dd1d576dbcdab926df203b1834eec129c441c06ab05bb3655160235182a8dc7d |
|
MD5 | 527ef2de55546aaa305dda22e636200e |
|
BLAKE2b-256 | 0bcd96ff05a70707f10d23115d44020059b6d4ec4988b18d04832db3e71acd8d |
Hashes for stringzilla-2.0.1-cp39-cp39-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 45350d46df426c1ec37a4a4082f3cc2131a551b9678d26bdebc434fd9af11450 |
|
MD5 | 2b2fd77c6081661c4f3d4d534e0de78a |
|
BLAKE2b-256 | c28e4fd3630eeb664e9c50a81b0c83fa295c2970923ebb8bef66cbf55c9131ee |
Hashes for stringzilla-2.0.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | fad9f9318f5048dd57b74e4e85e3f7198216fb365f13222ae2ee4acb00ff1c61 |
|
MD5 | 809569db2d9e70db86fd0c91ea151650 |
|
BLAKE2b-256 | d04719d5e3ae1b814102f838652d8095bece900ae0240bc84d0b72f4a92b0421 |
Hashes for stringzilla-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1c468823faa856b1a2413e221106263cf35d2e408b697f314b19b3d8701e9ee7 |
|
MD5 | 8e04dc8d04c3d02b4583fb20d5cda75f |
|
BLAKE2b-256 | 3230374f14f95cfc4f8d4e0835b7cf9f8aa0241110f0307c4e379fe8a3b9d3c5 |
Hashes for stringzilla-2.0.1-cp39-cp39-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b925cd957e6d85c607d331d9ca1cad6d1ae0832f3c89d32b385725e6adcb3d9e |
|
MD5 | 9635cc46abc9a6f4a06086ef047aa1bf |
|
BLAKE2b-256 | 3e149f29a497afe8662ff529aa2dc04f86585722fbd212e93683f3de01b00586 |
Hashes for stringzilla-2.0.1-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 31aed65fd6a700327e88c34d64b85d149ec4d1225d8dbd45439633da81ca1e9d |
|
MD5 | 3fcb70a0c1ba10efd042533840e23d1b |
|
BLAKE2b-256 | b422481baef56a54e83ea07a1e72258fac81fe81af70c3dd6f2feb8c0a467dbf |
Hashes for stringzilla-2.0.1-cp38-cp38-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | df998e7f474f2a317962e92fe985764b750db7a0a07f9f5833df8fa2d80731e8 |
|
MD5 | 4da2bb68dce78375c0e901dff3adc269 |
|
BLAKE2b-256 | a8d84b68bd125d071052e2db00e5f2261d243a33745c8f940f66a07802394acf |
Hashes for stringzilla-2.0.1-cp38-cp38-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 457429f90d11e4f2724dca85960504f3b1de0543766ca29bfc93a951092afe55 |
|
MD5 | e28c1b1620f3b42b2326adca9f2176e4 |
|
BLAKE2b-256 | 2b91894453eb63100c8c6797938dc2ce8bacacc37819ef45912476ea69c3a462 |
Hashes for stringzilla-2.0.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 933ae446ad7ea9156f53228350c8ff6ced680931f73812d1f0b09708d8ffa75d |
|
MD5 | 0a4f4b75174a472bab3038d6742095bd |
|
BLAKE2b-256 | 865b0ed41957b6a4334d45aabfe85a2e9575116214272572af541e6c2a62d341 |
Hashes for stringzilla-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9f35ef9ab95aae14bf95289a80fdf33713b03a1e27ff3ba517a2ac7e620b7d51 |
|
MD5 | e9e71f252b202a2258ff7f717fea7422 |
|
BLAKE2b-256 | 90a41b9089b5b29cffe916e6449684207c31d3e91f4e5b4344e91a448a73cba7 |
Hashes for stringzilla-2.0.1-cp38-cp38-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 18c1dae3d71bb24b8215ec87d82b2948b197b0bda419efd109d94c6846f3f707 |
|
MD5 | 18a037a1a22bb8a86028863b9a75cb5a |
|
BLAKE2b-256 | 16afd1b704796c0b61422fdede9616fd333ac7a143e64ecd7b03c1a7d0df20f9 |
Hashes for stringzilla-2.0.1-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8eb40d2cf7ccf73eb1be3cdb428b9842328d2332db1095de9ed0f840dc0ee707 |
|
MD5 | 8c070641ad576757f3c394c37050d2e0 |
|
BLAKE2b-256 | e529db96bc27f4e8523d1cbe9388502e3600a1b07c15d368e718ba964e79cb24 |
Hashes for stringzilla-2.0.1-cp37-cp37m-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 14a6a97c9ac7c9863201bc2f377c5faa84dffba52b5641d92f80e56759ea4ced |
|
MD5 | 1798bed394b52c6625f052eb111b01da |
|
BLAKE2b-256 | e5f97b9f758236f576d3b38ed51c271c4eeee227b87ac9da5fa39e2b7bcf478d |
Hashes for stringzilla-2.0.1-cp37-cp37m-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9611bc9bdd1a56865f08dfca85c1ae3cc4f0443826672efe91f5376457b68514 |
|
MD5 | b5cdde906c7b4deb0e57ae924ef2359a |
|
BLAKE2b-256 | c432b9696d96a6af0cfd0b68b7198c2dd2ebbe8dd880baf1f118d2799d4fbe6e |
Hashes for stringzilla-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f2b3fc14c971e9195499e202b7eb878da663787f7a49f30ef8e52ad450354b09 |
|
MD5 | edfe7315783a1528c8bea030e0066f4b |
|
BLAKE2b-256 | 419f38c7b6e32a53173db2e237e453013187f8ea7e7bf1507b0c1e640af9e5c1 |
Hashes for stringzilla-2.0.1-cp36-cp36m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5ff41cc59c8116d7d2634dcc9938ee58d5de0a662a1c675ea55af3aa18b7f6e6 |
|
MD5 | a93e32ef92bde8bc8e203fafab12694d |
|
BLAKE2b-256 | dd0db1f8e531fb866bec1816f7032b09af24b1f885405a306a652907eccc5eea |
Hashes for stringzilla-2.0.1-cp36-cp36m-manylinux_2_28_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 316521d86c214b36f7ae3d0f91346a09fe3b472aa1fb0ba56767494d4abe8619 |
|
MD5 | 080752cff31aa345b002b7b07df96221 |
|
BLAKE2b-256 | aadc018252cb0a90aefcf36a3ac6e9f666eef7624f9c53e8787e6ac2b34b86cd |
Hashes for stringzilla-2.0.1-cp36-cp36m-manylinux_2_28_aarch64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7061edc54475e98e87b012ccbe4021b8e560349d627426099bd42773b601531b |
|
MD5 | beb87342d45a7fdb49022559977bf4bd |
|
BLAKE2b-256 | 22a9804427000fbd3ac79a692de0c996f9e58d8ca35e996905db9465ed3e58b8 |
Hashes for stringzilla-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 182ca1a9df6ff7cf3a3dbc39eee47e4fd9214fba7ce892042537e0c96e4851d7 |
|
MD5 | 3009295def146bcb6dabbcdd825b5d0e |
|
BLAKE2b-256 | 0770e2c415dfa22b701676c79404b40c42ed5acaf7d07e4601c5c1450f27ac98 |