Một mục phía máy chủ trong kho dữ liệu GitHub của TopGit: ariya/FastLZ, 543 sao, nhóm Backend, C. Small & portable byte-aligned LZ77 compression
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
FastLZ (MIT license) is an ANSI C/C90 implementation of Lempel-Ziv 77 algorithm (LZ77) of lossless data compression. It is suitable to compress series of text/paragraphs, sequences of raw pixel data, or any other blocks of data with lots of repetition. It is not intended to be used on images, videos, and other formats of data typically already in an optimal compressed form.
The focus for FastLZ is a very fast compression and decompression, doing that at the cost of the compression ratio. As an illustration, the comparison with zlib when compressing enwik8 (also in more details):
Ratio
Compression
Decompression
FastLZ
54.2%
159 MB/s
305 MB/s
zlib -1
42.3%
50 MB/s
184 MB/s
zlib -9
36.5%
11 MB/s
185 MB/s
FastLZ is used by many software products, from a number of games (such as Death Stranding) to various open-source projects (Godot Engine, Facebook HHVM, Apache Traffic Server, Calligra Office, OSv, Netty, etc). It even serves as the basis for other compression projects like BLOSC.
For other implementations of byte-aligned LZ77, take a look at LZ4, Snappy, Density, LZO, LZF, LZJB, LZRW, etc.
Usage
FastLZ can be used directly in any C/C++ applications. For other programming languages/environments, use the corresponding binding:
Rust, available on Crates: cargo install fastlz
Python, available on PyPi: pip install fastlz
JavaScript, available on npm: npm install fastlz
Ruby, available on Rubygems: gem install fastlz
Lua via github.com/oneoo/lua-fastlz
FastLZ consists of only two files: fastlz.h and fastlz.c. Just add these files to your project in order to use FastLZ. For the detailed information on the API to perform compression and decompression, see fastlz.h.
For Vcpkg users, FastLZ is already available: vcpkg install fastlz.
A simple file compressor called 6pack is included as an example on how to use FastLZ. The corresponding decompressor is 6unpack.
FastLZ supports any standard-conforming ANSI C/C90 compiler, including the popular ones such as GCC, Clang, Visual Studio, and even Tiny CC. FastLZ works well on a number of architectures (32-bit and 64-bit, big endian and little endian), from Intel/AMD, PowerPC, System z, ARM, MIPS, and RISC-V.
The continuous integration system runs an extensive set of compression-decompression round trips on the following systems:
For more details, check the corresponding GitHub Actions build logs.
amd64
Linux
Windows
macOS
GCC
Clang
TinyCC
VS 2019
i686
Linux
Windows
macOS
GCC
Clang
TinyCC
VS 2019
i586
Linux
DOS
GCC
Linux
powerpc
GCC
ppc64(le)
GCC
GCC
s390x
GCC
armhf
GCC
arm64
GCC
mips(el)
GCC
GCC
mips64(el)
GCC
GCC
riscv
GCC
riscv64
GCC
Block Format
Let us assume that FastLZ compresses an array of bytes, called the uncompressed block, into another array of bytes, called the compressed block. To understand what will be stored in the compressed block, it is illustrative to demonstrate how FastLZ will decompress the block to retrieve the original uncompressed block.
The first 3-bit of the block, i.e. the 3 most-significant bits of the first byte, is the block tag. Currently the block tag determines the compression level used to produce the compressed block.
Block tag
Compression level
0
Level 1
1
Level 2
The content of the block will vary depending on the compression level.
Block Format for Level 1
FastLZ Level 1 implements LZ77 compression algorithm with 8 KB sliding window and up to 264 bytes of match length.
The compressed block consists of one or more instructions.
Each instruction starts with a 1-byte opcode, 2-byte opcode, or 3-byte opcode.
Instruction type
Opcode[0]
Opcode[1]
Opcode[2]
Literal run
000, L₄-L₀
-
-
Short match
M₂-M₀, R₁₂-R₈
R₇-R₀
-
Long match
111, R₁₂-R₈
M₇-M₀
R₇-R₀
Note that the very first instruction in a compressed block is always a literal run.
Literal run instruction
For the literal run instruction, there is one or more bytes following the code. This is called the literal run.
The 5 least-significant bits of opcode[0], L, determines the number of literals following the opcode. The value of 0 indicates a 1-byte literal run, 1 indicates a 2-byte literal run, and so on. The minimum literal run is 1 and the maximum literal run is 32.
The decompressor copies (L + 1) bytes of literal run, starting from the first one right after opcode.
Example: If the compressed block is a 4-byte array of [0x02, 0x41, 0x42, 0x43], then the opcode is 0x02 and that means a literal run of 3 bytes. The decompressor will then copy the subsequent 3 bytes, [0x41, 0x42, 0x43], to the output buffer. The output buffer now represents the (original) uncompressed block, [0x41, 0x42, 0x43].
Short match instruction
The 3 most-significant bits of opcode[0], M, determines the match length. The value of 1 indicates a 3-byte match, 2 indicates a 4-byte match and so on. The minimum match length is 3 and the maximum match length is 8.
The 5 least-significant bits of opcode[0] combined with the 8 bits of the opcode[1], R, determines the reference offset. Since the offset is encoded in 13 bits, the minimum is 0 and the maximum is 8191.
The following C code retrieves the match length and reference offset:
M = opcode[0] >> 5;
R = 256 * (opcode[0] << 5) + opcode[1];
The decompressor copies (M+2) bytes, starting from the location offsetted by R in the output buffer. Note that R is a back reference, i.e. the value of 0 corresponds the last byte in the output buffer, 1 is the second to last byte, and so forth.
Example 1: If the compressed block is a 7-byte array of [0x03, 0x41, 0x42, 0x43, 0x44, 0x20, 0x02], then there are two instructions in the there. The first instruction is the literal run of 4 bytes (due to L = 3). Thus, the decompressor copies 4 bytes to the output buffer, resulting in [0x41, 0x42, 0x43, 0x44]. The second instruction is the short match of 3 bytes (from M = 1, i.e 0x20 >> 5) and the offset of 2. Therefore, the compressor goes back 2 bytes from the last position, copies 3 bytes ([0x42, 0x43, 0x44]), and appends them to the output buffer. The output buffer now represents the complete uncompressed data, [0x41, 0x42, 0x43, 0x44, 0x42, 0x43, 0x44].
Example 2: If the compressed block is a 4-byte array of [0x00, 0x61, 0x40, 0x00], then there are two instructions in there. The first instruction is the literal run of just 1 byte (L = 0). Thus, the decompressor copies the byte (0x61) to the output buffer. The output buffer now becomes [0x61]. The second instruction is the short match of 4 bytes (from M = 2, i.e. 0x40 >> 5) and the offset of 0. Therefore, the decompressor copies 4 bytes starting using the back reference of 0 (i.e. the position of 0x61). The output buffer now represents the complete uncompressed data, [0x61, 0x61, 0x61, 0x61, 0x61].
Long match instruction
The value of opcode[1], M, determines the match length. The value of 0 indicates a 9-byte match, 1 indicates a 10-byte match and so on. The minimum match length is 9 and the maximum match length is 264.
The 5 least-significant bits of opcode[0] combined with the 8 bits of opcode[2], R, determines the reference offset. Since the offset is encoded in 13 bits, the minimum is 0 and the maximum is 8191.
The following C code retrieves the match length and reference offset:
M = opcode[1];
R = 256 * (opcode[0] << 5) + opcode[2];
The decompressor copies (M+9) bytes, starting from the location offsetted by R in the output buffer. Note that R is a back reference, i.e. the value of 0 corresponds to the last byte in the output buffer, 1 is for the second to last byte, and so forth.
Example: If the compressed block is a 4-byte array of [0x01, 0x44, 0x45, 0xE0, 0x01, 0x01], then there are two instructions in there. The first instruction is the literal run with the length of 2 (due to L = 1). Thus, the decompressor copies the 2-byte literal run ([0x44, 0x45]) to the output buffer. The second instruction is the long match with the match length of 10 (from M = 1) and the offset of 1. Therefore, the decompressor copies 10 bytes starting using the back reference of 1 (i.e. the position of 0x44). The output buffer now represents the complete uncompressed data, [0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45, 0x44, 0x45].
Decompressor Reference Implementation
The following 40-line C function implements a fully-functional decompressor for the above block format. Note that it is intended to be educational, e.g. no bound check is implemented, and therefore it is absolutely unsafe for production.
void fastlz_level1_decompress(const uint8_t* input, int length, uint8_t* output) {
int src = 0;
int dest = 0;
while (src < length) {
int type = input[src] >> 5;
if (type == 0) {
/* literal run */
int run = 1 + input[src];
src = src + 1;
while (run > 0) {
output[dest] = input[src];
src = src + 1;
dest = dest + 1;
run = run - 1;
}
} else if (type < 7) {
/* short match */
int ofs = 256 * (input[src] & 31) + input[src + 1];
int len = 2 + (input[src] >> 5);
src = src + 2;
int ref = dest - ofs - 1;
while (len > 0) {
output[dest] = output[ref];
ref = ref + 1;
dest = dest + 1;
len = len - 1;
}
} else {
/* long match */
int ofs = 256 * (input[src] & 31) + input[src + 2];
int len = 9 + input[src + 1];
src = src + 3;
int ref = dest - ofs - 1;
while (len > 0) {
output[dest] = output[ref];
ref = ref + 1;
dest = dest + 1;
len = len - 1;
}
}
}
}
ariya/FastLZ có 543 sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/ariya/FastLZ. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
ariya/FastLZ có phải mã nguồn mở không?
TopGit chưa ghi nhận license cho ariya/FastLZ. Phần lớn repo public trên GitHub là mã nguồn mở, nhưng điều khoản khác nhau từng repo — mở file LICENSE để xác nhận.
ariya/FastLZ còn đang phát triển không?
Commit gần nhất trên ariya/FastLZ là 2.0 năm trước (theo timestamp GitHub). Repo có 104 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
ariya/FastLZ là gì?
ariya/FastLZ (ariya/FastLZ) là dự án C trên GitHub. Theo mô tả gốc: Small & portable byte-aligned LZ77 compression
ariya/FastLZ viết bằng ngôn ngữ gì?
ariya/FastLZ chủ yếu viết bằng C. Trường "language" của GitHub dựa trên phần lớn byte ở nhánh mặc định.
Cùng nhóm Backend còn repo nào?
ariya/FastLZ thuộc nhóm Backend trên TopGit, cùng 17 topic GitHub. Trang Trending và Topics liệt kê các repo cùng số sao và cùng ngôn ngữ để so sánh.
Đọc thêm về ariya/FastLZ ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/ariya/FastLZ là nguồn chính thức.
Đọc đầy đủ README ở tab phía trên.
Muốn nghe thêm một ý kiến về FastLZ?
Hỏi một AI đọc được trang này — một cú bấm là có ngay nhận định về FastLZ.