09 - zlib 技术全景:DEFLATE 数据压缩引擎完整解析-Android系统底层用到的开源库

09 - zlib 技术全景:DEFLATE 数据压缩引擎完整解析

一、概述

1.1 项目简介

zlib 是由 Jean-loup Gailly 和 Mark Adler 开发的通用数据压缩库,实现了 DEFLATE 压缩算法,是互联网上使用最广泛的压缩库之一。

基本信息:

  • 版本: 1.2.13 (2022年10月13日)
  • 代码规模: ~16,000 行 C 代码
  • 核心算法: DEFLATE (LZ77 + Huffman 编码)
  • 位置 : external/zlib/
  • 许可证: BSD/Zlib License
  • RFC 标准: RFC 1950 (zlib), RFC 1951 (DEFLATE), RFC 1952 (gzip)

核心功能:

  • DEFLATE 压缩/解压缩
  • gzip 文件格式支持
  • zlib 包装格式支持
  • Adler-32 和 CRC-32 校验和
  • SIMD 优化 (ARM NEON, x86 SSE/PCLMULQDQ)
  • ZIP 文件处理 (Google 扩展)

1.2 压缩格式对比

格式 RFC 校验和 头部大小 用途
DEFLATE RFC 1951 0 原始压缩流
zlib RFC 1950 Adler-32 2 字节 + 6 字节尾 通用压缩
gzip RFC 1952 CRC-32 10+ 字节 + 8 字节尾 文件压缩

格式结构对比:

复制代码
DEFLATE:
┌───────────────────────┐
│  压缩数据块 (N bytes)  │
└───────────────────────┘

zlib:
┌─────┬───────────────────┬──────────┬──────────┐
│ CMF │     压缩数据      │ Adler-32 │  (2+N+4) │
│ FLG │                   │ (4 bytes)│          │
└─────┴───────────────────┴──────────┴──────────┘

gzip:
┌────────┬────────────────┬──────────┬────────┐
│ Header │   压缩数据     │  CRC-32  │  ISIZE │
│ (10+)  │                │ (4 bytes)│(4 bytes)│
└────────┴────────────────┴──────────┴────────┘

1.3 Android 集成概览

集成方式:

复制代码
Android Apps/Framework
         ↓
    libz.so (系统共享库)
         ↓
   ┌──────────┬────────────┐
   │ deflate  │  inflate   │
   │  (压缩)  │  (解压缩)  │
   └──────────┴────────────┘
         ↓
   SIMD 优化层
   (ARM NEON / x86 PCLMULQDQ)

使用场景:

  • APK 文件压缩 (ZIP 格式)
  • PNG 图像压缩 (DEFLATE)
  • HTTP 传输压缩 (gzip)
  • 数据库压缩 (SQLite)
  • 文件系统压缩
  • 网络协议压缩

二、架构设计

2.1 整体架构

复制代码
┌────────────────────────────────────────────────────────┐
│                    Public API Layer                     │
│  deflate(), inflate(), compress(), uncompress()         │
│  gzopen(), gzread(), gzwrite()                         │
└────────────────────────────────────────────────────────┘
                          ↓
┌────────────────────────────────────────────────────────┐
│                 Compression Engine                      │
├──────────────────────┬─────────────────────────────────┤
│  Deflate (deflate.c) │  Inflate (inflate.c)            │
│  • LZ77 匹配         │  • 状态机解析                    │
│  • 滑动窗口          │  • 符号解码                      │
│  • 哈希链            │  • 窗口复制                      │
│  • 延迟匹配          │  • 快速路径 (inffast.c)          │
└──────────────────────┴─────────────────────────────────┘
                          ↓
┌────────────────────────────────────────────────────────┐
│              Huffman Coding Layer                       │
│  • 动态树构建 (trees.c)                                 │
│  • 静态树 (固定 Huffman)                                │
│  • 树序列化/反序列化 (inftrees.c)                       │
│  • 位流操作                                             │
└────────────────────────────────────────────────────────┘
                          ↓
┌────────────────────────────────────────────────────────┐
│               Checksum & Utilities                      │
│  • Adler-32 (adler32.c, adler32_simd.c)                │
│  • CRC-32 (crc32.c, crc32_simd.c, crc_folding.c)       │
│  • 内存管理 (zutil.c)                                   │
└────────────────────────────────────────────────────────┘
                          ↓
┌────────────────────────────────────────────────────────┐
│              SIMD Optimization Layer                    │
│  • ARM NEON: Adler-32, CRC-32, 滑动窗口                │
│  • x86 SSE/PCLMULQDQ: CRC-32 折叠, Adler-32            │
│  • CPU 特性检测 (cpu_features.c)                        │
└────────────────────────────────────────────────────────┘

2.2 模块依赖关系

复制代码
gzopen/gzread/gzwrite (gzip 文件 I/O)
         ↓
   deflate/inflate (核心压缩/解压缩)
         ↓
   trees/inftrees (Huffman 编码)
         ↓
   adler32/crc32 (校验和)
         ↓
   cpu_features (SIMD 检测)

2.3 数据流设计

压缩流程:

复制代码
原始数据
    ↓
LZ77 滑动窗口匹配
    ↓ (literals + length/distance pairs)
Huffman 编码
    ↓ (动态/静态/存储块)
位流输出
    ↓
压缩数据 + 校验和

解压缩流程:

复制代码
压缩数据
    ↓
解析块头 (类型)
    ↓
Huffman 解码 → 符号流
    ↓
LZ77 窗口复制
    ↓
原始数据 + 校验和验证

三、核心组件详解

3.1 DEFLATE 压缩引擎 (deflate.c)

文件位置 : deflate.c (2,027 行)

3.1.1 核心概念

DEFLATE = LZ77 + Huffman 编码

  1. LZ77 算法: 滑动窗口模式匹配

    • 窗口大小: 32KB (默认)
    • 最小匹配: 3 字节
    • 最大匹配: 258 字节
    • 最大回溯: 32KB
  2. Huffman 编码: 符号到位序列的映射

    • 字面值树: 256 个字面值 + 29 个长度码
    • 距离树: 30 个距离码
    • 动态树: 每个块自适应
    • 静态树: 固定编码表
3.1.2 核心数据结构
c 复制代码
// deflate.h - Deflate 内部状态
typedef struct internal_state {
    z_streamp strm;               // 流对象指针

    // 滑动窗口
    Bytef *window;                // 窗口缓冲区 (2*w_size)
    ulg window_size;              // 窗口大小 (字节)
    Posf *prev;                   // 哈希链接表
    Posf *head;                   // 哈希表头

    // LZ77 状态
    uInt ins_h;                   // 当前插入哈希值
    uInt hash_size;               // 哈希表大小
    uInt hash_bits;               // log2(hash_size)
    uInt hash_mask;               // hash_size - 1

    uInt w_size;                  // LZ77 窗口大小
    uInt w_bits;                  // log2(w_size)
    uInt w_mask;                  // w_size - 1

    // 匹配信息
    uInt strstart;                // 当前字符串位置
    uInt match_start;             // 匹配起始位置
    uInt match_length;            // 最佳匹配长度
    uInt prev_match;              // 上次匹配位置
    int match_available;          // 延迟匹配标志

    uInt lookahead;               // 前瞻缓冲区字节数

    // Huffman 树
    ct_data dyn_ltree[HEAP_SIZE]; // 动态字面值树
    ct_data dyn_dtree[2*D_CODES]; // 动态距离树
    ct_data bl_tree[2*BL_CODES];  // 位长树

    // 块管理
    ulg opt_len;                  // 最优块长度
    ulg static_len;               // 静态块长度
    uInt matches;                 // 块内匹配数
    uInt insert;                  // 块内插入数

    // 位缓冲
    ush bi_buf;                   // 16 位输出缓冲区
    int bi_valid;                 // bi_buf 中有效位数

    // 压缩参数
    int level;                    // 压缩级别 0-9
    int strategy;                 // 压缩策略
    int good_match;               // 好匹配阈值
    int nice_match;               // 停止搜索阈值
    int max_lazy_match;           // 延迟匹配阈值
    int max_chain_length;         // 最大哈希链长度
} deflate_state;

// Huffman 树节点
typedef struct ct_data_s {
    union {
        ush freq;                 // 频率计数
        ush code;                 // 编码值
    } fc;
    union {
        ush dad;                  // 父节点
        ush len;                  // 编码长度
    } dl;
} ct_data;
3.1.3 压缩级别配置
c 复制代码
// deflate.c - 配置表 (每个级别的参数)
typedef struct config_s {
   ush good_length;     // 好匹配的最小长度
   ush max_lazy;        // 不进行延迟评估的最大长度
   ush nice_length;     // 停止搜索的充分好匹配
   ush max_chain;       // 最大哈希链遍历长度
   compress_func func;  // 压缩函数
} config;

local const config configuration_table[10] = {
/* 级别   good lazy nice chain  函数 */
/*  0 */ {0,    0,  0,    0, deflate_stored},  // 仅存储
/*  1 */ {4,    4,  8,    4, deflate_fast},    // 快速
/*  2 */ {4,    5, 16,    8, deflate_fast},
/*  3 */ {4,    6, 32,   32, deflate_fast},

/*  4 */ {4,    4, 16,   16, deflate_slow},    // 慢速(延迟匹配)
/*  5 */ {8,   16, 32,   32, deflate_slow},
/*  6 */ {8,   16, 128, 128, deflate_slow},    // 默认级别

/*  7 */ {8,   32, 128, 256, deflate_slow},
/*  8 */ {32, 128, 258, 1024, deflate_slow},
/*  9 */ {32, 258, 258, 4096, deflate_slow}};  // 最大压缩

级别说明:

  • 级别 0: 不压缩,直接存储 (用于已压缩数据)
  • 级别 1-3: 快速压缩,无延迟匹配
  • 级别 4-9: 慢速压缩,启用延迟匹配
3.1.4 哈希链匹配算法

滑动窗口哈希:

c 复制代码
// deflate.c - 插入字符串到哈希表
#define INSERT_STRING(s, str, match_head) \
   (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
    match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
    s->head[s->ins_h] = (Pos)(str))

// 更新哈希值 (3 字节滚动哈希)
#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)

最长匹配搜索:

c 复制代码
// deflate.c - 查找最长匹配
local uInt longest_match(deflate_state *s, IPos cur_match) {
    unsigned chain_length = s->max_chain_length;  // 最大搜索次数
    register Bytef *scan = s->window + s->strstart;
    register Bytef *match;
    register int len;
    int best_len = s->prev_length;                // 当前最佳长度
    int nice_match = s->nice_match;
    IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
        s->strstart - (IPos)MAX_DIST(s) : NIL;

    // 遍历哈希链
    do {
        match = s->window + cur_match;

        // 快速检查: 匹配末尾和开头
        if (match[best_len] != scan[best_len] ||
            match[best_len-1] != scan[best_len-1] ||
            *match != *scan ||
            *++match != scan[1]) continue;

        // 计算匹配长度 (最多 258 字节)
        scan += 2, match++;
        do {} while (*++scan == *++match && *++scan == *++match &&
                     *++scan == *++match && *++scan == *++match &&
                     *++scan == *++match && *++scan == *++match &&
                     *++scan == *++match && *++scan == *++match &&
                     scan < strend);

        len = MAX_MATCH - (int)(strend - scan);

        if (len > best_len) {
            s->match_start = cur_match;
            best_len = len;
            if (len >= nice_match) break;  // 足够好,停止搜索
        }

    } while ((cur_match = s->prev[cur_match & s->w_mask]) > limit &&
             --chain_length != 0);

    return best_len;
}
3.1.5 延迟匹配 (Lazy Matching)

概念: 延迟发送当前匹配,检查下一个位置是否有更好的匹配。

c 复制代码
// deflate.c - deflate_slow (延迟匹配)
local block_state deflate_slow(deflate_state *s, int flush) {
    IPos hash_head;
    int bflush;

    for (;;) {
        // 1. 查找当前位置的匹配
        hash_head = INSERT_STRING(s, s->strstart, hash_head);

        s->prev_length = s->match_length;
        s->prev_match = s->match_start;
        s->match_length = MIN_MATCH-1;

        if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
            s->strstart - hash_head <= MAX_DIST(s)) {
            s->match_length = longest_match(s, hash_head);
        }

        // 2. 延迟决策
        if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
            // 上次匹配更好,使用上次匹配
            uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;

            _tr_tally_dist(s, s->strstart -1 - s->prev_match,
                           s->prev_length - MIN_MATCH, bflush);

            // 前进 prev_length - 1 步
            s->lookahead -= s->prev_length - 1;
            s->prev_length -= 2;
            do {
                if (++s->strstart <= max_insert) {
                    INSERT_STRING(s, s->strstart, hash_head);
                }
            } while (--s->prev_length != 0);

            s->match_available = 0;
            s->match_length = MIN_MATCH-1;
            s->strstart++;

        } else if (s->match_available) {
            // 上次没有匹配,发送字面值
            _tr_tally_lit(s, s->window[s->strstart-1], bflush);
            s->strstart++;
            s->lookahead--;
        } else {
            // 标记延迟,继续前进
            s->match_available = 1;
            s->strstart++;
            s->lookahead--;
        }

        if (bflush) FLUSH_BLOCK(s, 0);
    }
}
3.1.6 压缩策略
c 复制代码
// zlib.h - 压缩策略
#define Z_DEFAULT_STRATEGY  0   // 默认策略 (混合 LZ77 + Huffman)
#define Z_FILTERED          1   // 过滤数据 (更多字面值)
#define Z_HUFFMAN_ONLY      2   // 仅 Huffman,禁用 LZ77
#define Z_RLE               3   // RLE (游程编码) 优化
#define Z_FIXED             4   // 固定 Huffman 树

策略选择:

  • DEFAULT: 一般数据 (文本,二进制)
  • FILTERED: PNG 图像数据
  • HUFFMAN_ONLY: 随机数据,LZ77 无效
  • RLE: 重复数据 (如位图)
  • FIXED: 小数据块,避免树开销

3.2 Huffman 编码模块 (trees.c)

文件位置 : trees.c (1,181 行)

3.2.1 Huffman 树构建

三棵树:

  1. 字面值/长度树 (Literal/Length Tree):

    • 0-255: 字面值
    • 256: 块结束标记
    • 257-285: 长度码 (3-258 字节)
    • 总共 286 个符号
  2. 距离树 (Distance Tree):

    • 0-29: 距离码 (1-32768 字节)
    • 30 个符号
  3. 编码长度树 (Code Length Tree):

    • 0-18: 元编码 (用于传输树结构)
    • 19 个符号

Huffman 算法实现:

c 复制代码
// trees.c - 构建 Huffman 树
local void build_tree(deflate_state *s, tree_desc *desc) {
    ct_data *tree = desc->dyn_tree;
    const ct_data *stree = desc->stat_desc->static_tree;
    int elems = desc->stat_desc->elems;
    int n, m;
    int max_code = -1;
    int node;

    // 1. 初始化堆 (频率排序)
    s->heap_len = 0, s->heap_max = HEAP_SIZE;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            s->heap[++(s->heap_len)] = max_code = n;
            s->depth[n] = 0;
        } else {
            tree[n].Len = 0;
        }
    }

    // 2. 构建 Huffman 树 (频率最小的两个节点合并)
    while (s->heap_len < 2) {
        node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
        tree[node].Freq = 1;
        s->depth[node] = 0;
        s->opt_len--; if (stree) s->static_len -= stree[node].Len;
    }
    desc->max_code = max_code;

    for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);

    node = elems;
    do {
        pqremove(s, tree, n);          // 取出最小频率节点
        m = s->heap[SMALLEST];         // 次小频率节点

        s->heap[--(s->heap_max)] = n;  // 保存到堆尾
        s->heap[--(s->heap_max)] = m;

        // 合并两个节点
        tree[node].Freq = tree[n].Freq + tree[m].Freq;
        s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
                                s->depth[n] : s->depth[m]) + 1);
        tree[n].Dad = tree[m].Dad = (ush)node;

        s->heap[SMALLEST] = node++;
        pqdownheap(s, tree, SMALLEST);

    } while (s->heap_len >= 2);

    s->heap[--(s->heap_max)] = s->heap[SMALLEST];

    // 3. 计算编码长度
    gen_bitlen(s, (tree_desc *)desc);

    // 4. 生成规范 Huffman 编码
    gen_codes((ct_data *)tree, max_code, s->bl_count);
}

编码长度限制:

c 复制代码
// trees.c - 限制编码长度到 MAX_BITS (15)
#define MAX_BITS 15

local void gen_bitlen(deflate_state *s, tree_desc *desc) {
    // ... 如果编码长度 > MAX_BITS,重新调整
    int overflow = 0;

    for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;

    // 从根节点开始分配长度
    tree[s->heap[s->heap_max]].Len = 0;

    for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
        n = s->heap[h];
        bits = tree[tree[n].Dad].Len + 1;
        if (bits > max_length) bits = max_length, overflow++;
        tree[n].Len = (ush)bits;

        if (n > desc->max_code) continue;
        s->bl_count[bits]++;
        // ...
    }

    // 处理溢出 (重新分配编码长度)
    if (overflow != 0) {
        // ... 代码省略
    }
}
3.2.2 动态 Huffman 块格式

块头结构:

复制代码
┌──────────────────────────────────────────┐
│  BFINAL (1 bit): 是否最后一个块           │
│  BTYPE  (2 bits): 块类型                 │
│    00 = 存储块 (无压缩)                   │
│    01 = 静态 Huffman                     │
│    10 = 动态 Huffman                     │
│    11 = 保留 (错误)                       │
└──────────────────────────────────────────┘

动态 Huffman 块头:
┌──────────────────────────────────────────┐
│  HLIT  (5 bits): 字面值/长度码数量 - 257  │
│  HDIST (5 bits): 距离码数量 - 1           │
│  HCLEN (4 bits): 编码长度码数量 - 4       │
│  Code Length Codes (3 bits each × HCLEN) │
│  Literal/Length Code Lengths             │
│  Distance Code Lengths                   │
│  Compressed Data                         │
└──────────────────────────────────────────┘

树序列化:

c 复制代码
// trees.c - 发送树结构
local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) {
    int rank;

    // 发送码数量
    send_bits(s, lcodes-257, 5);  // HLIT
    send_bits(s, dcodes-1,   5);  // HDIST
    send_bits(s, blcodes-4,  4);  // HCLEN

    // 发送编码长度树 (19 个符号,按特定顺序)
    for (rank = 0; rank < blcodes; rank++) {
        send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
    }

    // 使用编码长度树发送字面值树
    send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1);

    // 使用编码长度树发送距离树
    send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1);
}
3.2.3 长度/距离编码

长度码映射:

c 复制代码
// trees.c - 长度额外位
local const int extra_lbits[LENGTH_CODES] = {
    0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
};

// 长度基值
local const int base_length[LENGTH_CODES] = {
    3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,
    35,43,51,59,67,83,99,115,131,163,195,227,258
};

// 示例: 长度 66 → 码 269 + 额外位 1
// base_length[269-257] = 67, 67-1=66, 需要 1 位表示偏移

距离码映射:

c 复制代码
// trees.c - 距离额外位
local const int extra_dbits[D_CODES] = {
    0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
};

// 距离基值
local const int base_dist[D_CODES] = {
    1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
    257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577
};

// 示例: 距离 513 → 码 18 + 额外位 0

3.3 DEFLATE 解压缩引擎 (inflate.c)

文件位置 : inflate.c (1,474 行)

3.3.1 状态机设计

27+ 状态:

c 复制代码
// inflate.h - 解压缩状态
typedef enum {
    HEAD,        // 读取 zlib/gzip 头
    FLAGS,       // 处理标志位
    TIME,        // gzip 时间戳
    OS,          // gzip 操作系统
    EXLEN,       // gzip 额外字段长度
    EXTRA,       // gzip 额外字段
    NAME,        // gzip 文件名
    COMMENT,     // gzip 注释
    HCRC,        // gzip 头 CRC
    DICTID,      // zlib 字典 ID
    DICT,        // 等待字典
    TYPE,        // 块类型
    TYPEDO,      // 块类型处理
    STORED,      // 存储块处理
    COPY_,       // 复制存储数据
    COPY,        // 复制中
    TABLE,       // 读取动态树参数
    LENLENS,     // 读取编码长度树
    CODELENS,    // 读取字面值/距离树长度
    LEN_,        // 读取长度码
    LEN,         // 处理长度
    LENEXT,      // 读取长度额外位
    DIST,        // 读取距离码
    DISTEXT,     // 读取距离额外位
    MATCH,       // 复制匹配数据
    LIT,         // 输出字面值
    CHECK,       // 校验和检查
    LENGTH,      // gzip 未压缩长度
    DONE,        // 完成
    BAD,         // 错误
    MEM,         // 内存不足
    SYNC         // 同步搜索
} inflate_mode;

状态转换示例:

复制代码
HEAD → FLAGS → TYPE → (STORED/TABLE/LEN) → ... → CHECK → DONE
                ↓ (动态 Huffman)
            TABLE → LENLENS → CODELENS → LEN → DIST → MATCH → CHECK
3.3.2 核心解压缩循环
c 复制代码
// inflate.c - inflate() 主循环
int ZEXPORT inflate(z_streamp strm, int flush) {
    struct inflate_state FAR *state;
    // ...

    for (;;) {
        switch (state->mode) {

        case HEAD:
            // 解析 zlib/gzip 头
            // ...
            state->mode = FLAGS;

        case FLAGS:
            // 处理标志
            // ...
            state->mode = TIME;

        // ... 其他头部状态

        case TYPE:
            // 读取块类型 (3 位)
            NEEDBITS(3);
            state->last = BITS(1);        // BFINAL
            DROPBITS(1);
            switch (BITS(2)) {
            case 0:                       // 存储块
                state->mode = STORED;
                break;
            case 1:                       // 固定 Huffman
                fixedtables(state);
                state->mode = LEN_;
                break;
            case 2:                       // 动态 Huffman
                state->mode = TABLE;
                break;
            case 3:
                strm->msg = (char *)"invalid block type";
                state->mode = BAD;
            }
            DROPBITS(2);
            break;

        case TABLE:
            // 读取动态树参数
            NEEDBITS(14);
            state->nlen = BITS(5) + 257;  // HLIT
            DROPBITS(5);
            state->ndist = BITS(5) + 1;   // HDIST
            DROPBITS(5);
            state->ncode = BITS(4) + 4;   // HCLEN
            DROPBITS(4);
            state->mode = LENLENS;

        case LENLENS:
            // 读取编码长度树
            // ...
            state->mode = CODELENS;

        case CODELENS:
            // 解码字面值/长度树和距离树
            // ...
            state->mode = LEN_;

        case LEN_:
            if (flush == Z_TREES) goto inf_leave;
            /* fall through */

        case LEN:
            // 解码字面值/长度
            // 使用 inffast() 快速路径
            if (have >= 6 && left >= 258) {
                RESTORE();
                inflate_fast(strm, out);
                LOAD();
                break;
            }
            // ... 慢速路径

        case DIST:
            // 解码距离
            // ...
            state->mode = MATCH;

        case MATCH:
            // 复制匹配数据
            copy = state->offset;
            from = state->window + (state->wnext - copy);
            while (state->length) {
                *put++ = *from++;
                state->length--;
            }
            state->mode = LEN;
            break;

        // ... 其他状态
        }
    }

inf_leave:
    RESTORE();
    return ret;
}
3.3.3 快速解压缩路径 (inffast.c)

文件位置 : inffast.c (332 行)

优化策略:

  • 批量处理完整符号 (避免位操作开销)
  • 展开循环 (减少分支预测失败)
  • 预先检查缓冲区 (保证至少 258 字节输出空间)
c 复制代码
// inffast.c - 快速解压缩
void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
    struct inflate_state FAR *state;
    unsigned char FAR *in;      // 输入指针
    unsigned char FAR *last;    // 输入缓冲区末尾
    unsigned char FAR *out;     // 输出指针
    unsigned char FAR *beg;     // 输出窗口起始
    unsigned char FAR *end;     // 输出缓冲区末尾
    unsigned wsize;             // 窗口大小
    unsigned whave;             // 窗口有效数据
    unsigned wnext;             // 窗口下一个位置
    unsigned char FAR *window;  // 窗口指针
    unsigned long hold;         // 位缓冲区 (64 位)
    unsigned bits;              // 有效位数
    code const FAR *lcode;      // 字面值/长度码表
    code const FAR *dcode;      // 距离码表
    unsigned lmask;             // 字面值码掩码
    unsigned dmask;             // 距离码掩码
    code here;                  // 当前符号
    unsigned op;                // 操作码
    unsigned len;               // 匹配长度
    unsigned dist;              // 匹配距离
    unsigned char FAR *from;    // 复制源

    // 初始化
    // ...

    // 快速循环 (保证有足够输入和输出)
    do {
        // 1. 读取字面值/长度码
        here = lcode[hold & lmask];

      dolen:
        op = (unsigned)(here.bits);
        hold >>= op;
        bits -= op;
        op = (unsigned)(here.op);

        if (op == 0) {                          // 字面值
            *out++ = (unsigned char)(here.val);
        }
        else if (op & 16) {                     // 长度
            len = (unsigned)(here.val);
            op &= 15;
            if (op) {
                len += (unsigned)hold & ((1U << op) - 1);
                hold >>= op;
                bits -= op;
            }

            // 2. 读取距离码
            here = dcode[hold & dmask];

          dodist:
            op = (unsigned)(here.bits);
            hold >>= op;
            bits -= op;
            op = (unsigned)(here.op);

            if (op & 16) {                      // 距离
                dist = (unsigned)(here.val);
                op &= 15;
                if (op) {
                    dist += (unsigned)hold & ((1U << op) - 1);
                    hold >>= op;
                    bits -= op;
                }

                // 3. 复制匹配数据
                from = out - dist;
                if (from < beg) {               // 从窗口复制
                    from += wsize;
                    // ... 窗口复制逻辑
                }

                // 快速复制 (8 字节块)
                if (len > 2) {
                    *out++ = *from++;
                    *out++ = *from++;
                    *out++ = *from++;
                    len -= 3;
                }
                while (len > 0) {
                    *out++ = *from++;
                    len--;
                }
            }
            // ... 错误处理
        }
        else if ((op & 64) == 0) {              // 多级编码
            here = lcode[here.val + (hold & ((1U << op) - 1))];
            goto dolen;
        }
        else if (op & 32) {                     // 块结束
            state->mode = TYPE;
            break;
        }
        else {
            // 错误
        }
    } while (in < last && out < end);

    // 清理
    // ...
}
3.3.4 动态树解码 (inftrees.c)

文件位置 : inftrees.c (414 行)

解码表构建:

c 复制代码
// inftrees.c - 从编码长度构建解码表
int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
                                 unsigned codes, code FAR * FAR *table,
                                 unsigned FAR *bits, unsigned short FAR *work) {
    unsigned len;               // 编码长度
    unsigned sym;               // 符号索引
    unsigned min, max;          // 最小/最大编码长度
    unsigned root;              // 根表大小
    unsigned curr;              // 当前表大小
    unsigned drop;              // 下降位数
    int left;                   // 剩余码数
    unsigned used;              // 已用码数
    unsigned huff;              // Huffman 码
    unsigned incr;              // 增量
    unsigned fill;              // 填充值
    unsigned low;               // 低位掩码
    unsigned mask;              // 当前掩码
    code here;                  // 表项
    code FAR *next;             // 下一个表
    const unsigned short FAR *base;     // 基值表
    const unsigned short FAR *extra;    // 额外位表
    unsigned match;             // 匹配值

    // 1. 统计每个长度的码数量
    for (len = 0; len <= MAXBITS; len++)
        count[len] = 0;
    for (sym = 0; sym < codes; sym++)
        count[lens[sym]]++;

    // 2. 计算偏移量
    root = *bits;
    for (max = MAXBITS; max >= 1; max--)
        if (count[max] != 0) break;
    if (root > max) root = max;
    if (max == 0) {                     // 无符号
        // ...
        return 0;
    }
    for (min = 1; min < max; min++)
        if (count[min] != 0) break;
    if (root < min) root = min;

    // 3. 检查完整性 (Kraft 不等式)
    left = 1;
    for (len = 1; len <= MAXBITS; len++) {
        left <<= 1;
        left -= count[len];
        if (left < 0) return -1;        // 过度订阅
    }
    if (left > 0 && (type == CODES || max != 1))
        return -1;                      // 不完整集合

    // 4. 生成解码表
    offs[1] = 0;
    for (len = 1; len < MAXBITS; len++)
        offs[len + 1] = offs[len] + count[len];

    for (sym = 0; sym < codes; sym++)
        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;

    // 5. 填充表
    // ... (代码省略,生成多级查找表)

    return 0;
}

3.4 校验和模块

3.4.1 Adler-32 校验和 (adler32.c)

算法:

c 复制代码
// adler32.c - Adler-32 计算
#define BASE 65521U       // 最大素数 < 2^16
#define NMAX 5552         // 最大块大小 (防止溢出)

// Adler-32 = (B << 16) | A
// A = 1 + sum(D[i]) mod BASE
// B = (1 + D[0]) + (1 + D[0] + D[1]) + ... mod BASE

uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
    unsigned long sum2;
    unsigned n;

    // 分离 A 和 B
    sum2 = (adler >> 16) & 0xffff;
    adler &= 0xffff;

    // 处理单字节
    if (len == 1) {
        adler += buf[0];
        if (adler >= BASE)
            adler -= BASE;
        sum2 += adler;
        if (sum2 >= BASE)
            sum2 -= BASE;
        return adler | (sum2 << 16);
    }

    // 快速路径: SIMD
#ifdef ADLER32_SIMD_SSSE3
    if (len >= 64) {
        unsigned long len_orig = len;
        len = adler32_simd_(adler, buf, len, &sum2);
        buf += len_orig - len;
    }
#endif

    // 标量路径
    if (len < 16) {
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        if (adler >= BASE)
            adler -= BASE;
        MOD28(sum2);
        return adler | (sum2 << 16);
    }

    // 块处理 (NMAX 字节)
    while (len >= NMAX) {
        len -= NMAX;
        n = NMAX / 16;
        do {
            DO16(buf);
            buf += 16;
        } while (--n);
        MOD(adler);
        MOD(sum2);
    }

    // 剩余字节
    if (len) {
        while (len >= 16) {
            len -= 16;
            DO16(buf);
            buf += 16;
        }
        while (len--) {
            adler += *buf++;
            sum2 += adler;
        }
        MOD(adler);
        MOD(sum2);
    }

    return adler | (sum2 << 16);
}

// 展开宏
#define DO16(buf) \
    adler += (buf)[0]; sum2 += adler; \
    adler += (buf)[1]; sum2 += adler; \
    adler += (buf)[2]; sum2 += adler; \
    /* ... 共 16 行 */

SIMD 优化 (adler32_simd.c):

c 复制代码
// adler32_simd.c - SSSE3 优化
#ifdef ADLER32_SIMD_SSSE3

#include <emmintrin.h>  // SSE2
#include <tmmintrin.h>  // SSSE3

uint32_t adler32_simd_(uint32_t adler, const unsigned char *buf,
                       z_size_t len, uint32_t *sum2) {
    __m128i vA, vB;
    __m128i vByte;
    __m128i vCOL_SCALE, vROW_SCALE;

    // 初始化向量
    vA = _mm_cvtsi32_si128(adler);
    vB = _mm_cvtsi32_si128(*sum2);

    vCOL_SCALE = _mm_set_epi8(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
    vROW_SCALE = _mm_set1_epi16(16);

    // 处理 32 字节块
    while (len >= 32) {
        // 加载 16 字节 (两次)
        vByte = _mm_loadu_si128((__m128i*)buf);

        // 水平加法 (使用 _mm_sad_epu8)
        __m128i vSum = _mm_sad_epu8(vByte, _mm_setzero_si128());

        // 累加到 A
        vA = _mm_add_epi32(vA, vSum);

        // 加权累加到 B (列权重 1-16)
        __m128i vMul = _mm_maddubs_epi16(vByte, vCOL_SCALE);
        vMul = _mm_madd_epi16(vMul, _mm_set1_epi16(1));
        vB = _mm_add_epi32(vB, vMul);

        // ... 第二个 16 字节

        buf += 32;
        len -= 32;
    }

    // 提取结果
    adler = _mm_cvtsi128_si32(vA);
    *sum2 = _mm_cvtsi128_si32(vB);

    // 模运算
    adler %= BASE;
    *sum2 %= BASE;

    return len;
}

#endif
3.4.2 CRC-32 校验和 (crc32.c)

查表算法:

c 复制代码
// crc32.c - CRC-32 查表
local const z_crc_t FAR crc_table[256] = {
  0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL,
  // ... 256 项预计算表
};

#define DO1 crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1

uLong ZEXPORT crc32_z(uLong crc, const unsigned char FAR *buf, z_size_t len) {
    if (buf == Z_NULL) return 0UL;

#ifdef CRC32_SIMD_SSE42_PCLMUL
    if (len >= 64) {
        return crc32_sse42_simd_(buf, len, crc);
    }
#endif

    crc = crc ^ 0xffffffffUL;
    while (len >= 8) {
        DO8;
        len -= 8;
    }
    if (len) do {
        DO1;
    } while (--len);
    return crc ^ 0xffffffffUL;
}

SIMD 优化 (crc_folding.c):

c 复制代码
// crc_folding.c - PCLMULQDQ 折叠算法
#ifdef CRC32_SIMD_SSE42_PCLMUL

#include <emmintrin.h>   // SSE2
#include <smmintrin.h>   // SSE4.2
#include <wmmintrin.h>   // PCLMULQDQ

// 4 路并行 CRC (每路处理 128 位)
void crc_fold_init(deflate_state *const s) {
    __m128i *p = (__m128i *)s->crc0;
    p[0] = _mm_cvtsi32_si128(0x9db42487);  // 折叠常数
    p[1] = _mm_setzero_si128();
    p[2] = _mm_setzero_si128();
    p[3] = _mm_setzero_si128();
}

void crc_fold_copy(deflate_state *const s, unsigned char *dst,
                   const unsigned char *src, long len) {
    __m128i xmm0, xmm1, xmm2, xmm3, xmm4;
    __m128i xmm_fold = _mm_load_si128((__m128i *)s->crc0);

    while (len >= 64) {
        // 加载 4×16 字节
        xmm0 = _mm_loadu_si128((__m128i *)src);
        xmm1 = _mm_loadu_si128((__m128i *)(src + 16));
        xmm2 = _mm_loadu_si128((__m128i *)(src + 32));
        xmm3 = _mm_loadu_si128((__m128i *)(src + 48));

        // 无进位乘法 (PCLMULQDQ)
        xmm4 = _mm_clmulepi64_si128(xmm_fold, xmm_fold, 0x10);  // 低位
        xmm_fold = _mm_clmulepi64_si128(xmm_fold, xmm_fold, 0x01);  // 高位

        // 异或折叠
        xmm_fold = _mm_xor_si128(xmm_fold, xmm4);
        xmm_fold = _mm_xor_si128(xmm_fold, xmm0);

        // ... 类似处理 xmm1, xmm2, xmm3

        // 复制到目标
        _mm_storeu_si128((__m128i *)dst, xmm0);
        // ...

        src += 64;
        dst += 64;
        len -= 64;
    }

    _mm_store_si128((__m128i *)s->crc0, xmm_fold);
}

// 折叠 512 位 → 32 位
unsigned crc_fold_512to32(deflate_state *const s) {
    __m128i xmm0, xmm1, xmm2, xmm3;

    // 加载 4×128 位 CRC
    xmm0 = _mm_load_si128((__m128i *)s->crc0);
    xmm1 = _mm_load_si128((__m128i *)s->crc1);
    xmm2 = _mm_load_si128((__m128i *)s->crc2);
    xmm3 = _mm_load_si128((__m128i *)s->crc3);

    // 折叠 4 路 → 2 路 → 1 路 → 32 位
    // ... (复杂的 PCLMULQDQ 折叠算法)

    return _mm_extract_epi32(xmm0, 2);
}

#endif

3.5 gzip 文件 I/O 模块

3.5.1 gzip 文件格式
复制代码
┌─────────────────────────────────────────────────┐
│  Header (10 bytes)                               │
├──────┬────┬────┬────┬────┬────┬────┬────┬────┬───┤
│  ID1 │ID2 │ CM │FLG │MTIME (4) │ XFL│ OS │       │
│ 0x1F │0x8B│ 8  │bits│ timestamp│    │    │       │
└──────┴────┴────┴────┴──────────┴────┴────┴───────┘
          ↓ (可选字段,取决于 FLG)
┌─────────────────────────────────────────────────┐
│  Extra Field (FEXTRA)                            │
│  Original Filename (FNAME)                       │
│  Comment (FCOMMENT)                              │
│  Header CRC16 (FHCRC)                            │
└─────────────────────────────────────────────────┘
          ↓
┌─────────────────────────────────────────────────┐
│  Compressed Data (DEFLATE blocks)                │
└─────────────────────────────────────────────────┘
          ↓
┌──────────────────┬──────────────────────────────┐
│  CRC32 (4 bytes) │  ISIZE (4 bytes)             │
│  数据校验和      │  原始数据长度 (mod 2^32)     │
└──────────────────┴──────────────────────────────┘
3.5.2 gzip 文件打开 (gzlib.c)
c 复制代码
// gzlib.c - gzip 文件句柄
typedef struct {
    int have;               // 缓冲区数据量
    unsigned char *next;    // 缓冲区指针
    z_off64_t pos;          // 文件位置
    z_off64_t start;        // 数据起始位置
    z_off64_t raw;          // 原始位置
    int size;               // 缓冲区大小
    unsigned char *in;      // 输入缓冲区
    unsigned char *out;     // 输出缓冲区
    int direct;             // 直接模式 (无压缩)
    int how;                // 读/写/追加
    z_off64_t eof;          // 文件末尾
    z_stream strm;          // zlib 流
    char *path;             // 文件路径
    int fd;                 // 文件描述符
    int mode;               // 文件模式
    unsigned char *msg;     // 错误消息
} gz_state;

gzFile ZEXPORT gzopen(const char *path, const char *mode) {
    gz_statep state;

    // 解析模式 ("r", "w", "a", "rb", "wb9", etc.)
    // ...

    // 分配状态
    state = (gz_statep)malloc(sizeof(gz_state));
    if (state == NULL)
        return NULL;

    state->size = GZBUFSIZE;      // 默认 8KB
    state->want = GZBUFSIZE;
    state->msg = NULL;

    // 打开文件
    state->fd = open(path, oflag, 0666);
    if (state->fd == -1) {
        free(state);
        return NULL;
    }

    // 初始化 zlib 流
    if (state->mode == GZ_READ) {
        state->strm.avail_in = 0;
        state->strm.next_in = Z_NULL;
        if (inflateInit2(&state->strm, 15 + 16) != Z_OK) {  // +16 = gzip 格式
            close(state->fd);
            free(state);
            return NULL;
        }
    } else {
        deflateInit2(&state->strm, state->level, Z_DEFLATED,
                     15 + 16, 8, state->strategy);  // +16 = gzip 格式
    }

    return (gzFile)state;
}
3.5.3 gzip 读取 (gzread.c)
c 复制代码
// gzread.c - 读取 gzip 数据
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
    gz_statep state = (gz_statep)file;

    // 读取头部 (首次)
    if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
        gzrewind(state);

    // 主读取循环
    while (len) {
        // 从缓冲区复制
        if (state->x.have) {
            unsigned n = state->x.have > len ? len : state->x.have;
            memcpy(buf, state->x.next, n);
            state->x.next += n;
            state->x.have -= n;
            state->x.pos += n;
            buf = (char *)buf + n;
            len -= n;
        }

        // 解压缩更多数据
        if (len && state->eof == 0) {
            // 读取压缩数据
            if (state->strm.avail_in == 0) {
                state->strm.avail_in = read(state->fd, state->in, state->size);
                if (state->strm.avail_in == 0) {
                    state->eof = 1;
                    break;
                }
                state->strm.next_in = state->in;
            }

            // 解压缩
            state->strm.avail_out = state->size;
            state->strm.next_out = state->out;

            int ret = inflate(&state->strm, Z_NO_FLUSH);

            if (ret == Z_STREAM_END) {
                // 验证 CRC 和 ISIZE
                unsigned long crc, len;
                // ... 读取尾部 8 字节
                if (crc != state->strm.adler) {
                    state->msg = "incorrect data check";
                    return -1;
                }
                state->eof = 1;
            }

            state->x.have = state->size - state->strm.avail_out;
            state->x.next = state->out;
        }
    }

    return (int)(start - len);
}
3.5.4 gzip 写入 (gzwrite.c)
c 复制代码
// gzwrite.c - 写入 gzip 数据
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
    gz_statep state = (gz_statep)file;

    // 写入头部 (首次)
    if (state->size == 0 && gz_init(state) == -1)
        return 0;

    // 更新 CRC
    state->strm.adler = crc32(state->strm.adler, (const Bytef *)buf, len);

    // 主压缩循环
    state->strm.next_in = (z_const Bytef *)buf;
    state->strm.avail_in = len;

    do {
        // 输出缓冲区已满,刷新
        if (state->strm.avail_out == 0) {
            if (write(state->fd, state->out, state->size) != state->size) {
                state->msg = "write error";
                return 0;
            }
            state->strm.next_out = state->out;
            state->strm.avail_out = state->size;
        }

        // 压缩数据
        deflate(&state->strm, Z_NO_FLUSH);

    } while (state->strm.avail_in != 0);

    state->x.pos += len;
    return (int)len;
}

// gzclose.c - 关闭文件
int ZEXPORT gzclose(gzFile file) {
    gz_statep state = (gz_statep)file;

    if (state->mode == GZ_WRITE) {
        // 刷新剩余数据
        deflate(&state->strm, Z_FINISH);

        // 写入尾部 (CRC32 + ISIZE)
        put_byte(state, state->strm.adler & 0xff);
        put_byte(state, (state->strm.adler >> 8) & 0xff);
        put_byte(state, (state->strm.adler >> 16) & 0xff);
        put_byte(state, (state->strm.adler >> 24) & 0xff);

        put_byte(state, state->strm.total_in & 0xff);
        put_byte(state, (state->strm.total_in >> 8) & 0xff);
        put_byte(state, (state->strm.total_in >> 16) & 0xff);
        put_byte(state, (state->strm.total_in >> 24) & 0xff);

        deflateEnd(&state->strm);
    } else {
        inflateEnd(&state->strm);
    }

    close(state->fd);
    free(state);
    return Z_OK;
}

3.6 SIMD 优化层

3.6.1 CPU 特性检测 (cpu_features.c)
c 复制代码
// cpu_features.c - 运行时 CPU 特性检测

#if defined(__ARM_NEON__) || defined(ARMV8_OS_LINUX)
#include <sys/auxv.h>
#include <asm/hwcap.h>

int arm_cpu_enable_crc32 = 0;
int arm_cpu_enable_pmull = 0;

void cpu_check_features(void) {
    unsigned long hwcap = getauxval(AT_HWCAP);

#ifdef HWCAP_CRC32
    if (hwcap & HWCAP_CRC32)
        arm_cpu_enable_crc32 = 1;
#endif

#ifdef HWCAP_PMULL
    if (hwcap & HWCAP_PMULL)
        arm_cpu_enable_pmull = 1;
#endif
}

#elif defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>

int x86_cpu_enable_sse2 = 0;
int x86_cpu_enable_ssse3 = 0;
int x86_cpu_enable_sse42 = 0;
int x86_cpu_enable_pclmul = 0;

void cpu_check_features(void) {
    unsigned int eax, ebx, ecx, edx;

    // CPUID 功能 1 (SSE2, SSSE3)
    if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
        if (edx & (1 << 26)) x86_cpu_enable_sse2 = 1;
        if (ecx & (1 << 9))  x86_cpu_enable_ssse3 = 1;
        if (ecx & (1 << 20)) x86_cpu_enable_sse42 = 1;
        if (ecx & (1 << 1))  x86_cpu_enable_pclmul = 1;
    }
}

#else
void cpu_check_features(void) {
    // 不支持
}
#endif
3.6.2 滑动窗口哈希 SIMD (slide_hash_simd.h)
c 复制代码
// slide_hash_simd.h - 批量更新哈希表

#ifdef __SSE2__
#include <emmintrin.h>

// SSE2 版本: 8×uint16_t / 迭代
#define Z_SLIDE_HASH_SIMD(table, size, vector_wsize) \
    do { \
        const Posf* const end = table + size; \
        while (table != end) { \
            __m128i vO = _mm_loadu_si128((__m128i *)(table + 0)); \
            vO = _mm_subs_epu16(vO, vector_wsize);  /* 饱和减法 */ \
            _mm_storeu_si128((__m128i *)(table + 0), vO); \
            table += 8; \
        } \
    } while (0)

#elif defined(__ARM_NEON)
#include <arm_neon.h>

// NEON 版本: 16×uint16_t / 迭代
#define Z_SLIDE_HASH_SIMD(table, size, vector_wsize) \
    do { \
        const Posf* const end = table + size; \
        while (table != end) { \
            uint16x8_t v0 = vld1q_u16(table + 0); \
            uint16x8_t v1 = vld1q_u16(table + 8); \
            v0 = vqsubq_u16(v0, vector_wsize);  /* 饱和减法 */ \
            v1 = vqsubq_u16(v1, vector_wsize); \
            vst1q_u16(table + 0, v0); \
            vst1q_u16(table + 8, v1); \
            table += 16; \
        } \
    } while (0)

#else
// 标量版本
#define Z_SLIDE_HASH_SIMD(table, size, wsize) \
    slide_hash_c(table, size, wsize)
#endif

使用示例:

c 复制代码
// deflate.c - 滑动窗口
local void slide_hash(deflate_state *s) {
    unsigned n, m;
    Posf *p;
    uInt wsize = s->w_size;

#ifdef HAVE_BUILTIN_CTZ
    // 向量化路径
    const __m128i xmm_wsize = _mm_set1_epi16(wsize);

    Z_SLIDE_HASH_SIMD(s->head, s->hash_size, xmm_wsize);
    Z_SLIDE_HASH_SIMD(s->prev, wsize, xmm_wsize);
#else
    // 标量路径
    m = s->hash_size;
    p = &s->head[m];
    do {
        m = *--p;
        *p = (Pos)(m >= wsize ? m - wsize : NIL);
    } while (--n);

    m = wsize;
    p = &s->prev[m];
    do {
        m = *--p;
        *p = (Pos)(m >= wsize ? m - wsize : NIL);
    } while (--n);
#endif
}

四、Android 集成

4.1 构建系统 (Android.bp)

主库定义:

python 复制代码
// Android.bp - zlib 构建配置

// 静态库 (内部使用)
cc_library {
    name: "libz_static",
    host_supported: true,
    vendor_available: true,
    recovery_available: true,

    srcs: [
        "adler32.c",
        "compress.c",
        "crc32.c",
        "deflate.c",
        "gzclose.c",
        "gzlib.c",
        "gzread.c",
        "gzwrite.c",
        "infback.c",
        "inflate.c",
        "inftrees.c",
        "inffast.c",
        "trees.c",
        "uncompr.c",
        "zutil.c",

        // SIMD 优化
        "adler32_simd.c",
        "crc32_simd.c",
        "cpu_features.c",
    ],

    cflags: [
        "-O3",
        "-DHAVE_HIDDEN",
        "-DZLIB_CONST",
        "-Wall",
        "-Werror",
        "-Wno-unused",
        "-Wno-unused-parameter",
    ],

    // 架构特定标志
    arch: {
        arm: {
            cflags: [
                "-DADLER32_SIMD_NEON",
            ],
            neon: {
                cflags: [
                    "-DCRC32_ARMV8_CRC32",
                    "-DARMV8_OS_LINUX",
                ],
            },
        },
        arm64: {
            cflags: [
                "-DADLER32_SIMD_NEON",
                "-DINFLATE_CHUNK_READ_64LE",
                "-DCRC32_ARMV8_CRC32",
                "-DARMV8_OS_LINUX",
            ],
        },
        x86: {
            cflags: [
                "-DX86_NOT_WINDOWS",
                "-DCPU_NO_SIMD",  // 主机构建:禁用 SIMD
            ],
        },
        x86_64: {
            cflags: [
                "-DX86_NOT_WINDOWS",
                "-DINFLATE_CHUNK_READ_64LE",
                "-DADLER32_SIMD_SSSE3",
                "-DCRC32_SIMD_SSE42_PCLMUL",
            ],
        },
    },

    export_include_dirs: ["."],

    apex_available: [
        "com.android.runtime",
        "//apex_available:platform",
    ],
}

// 共享库 (系统导出)
cc_library {
    name: "libz",
    host_supported: true,
    vendor_available: true,
    vndk: {
        enabled: true,
    },

    whole_static_libs: ["libz_static"],

    unique_host_soname: true,
    static_ndk_lib: true,

    stubs: {
        versions: ["29", "30"],
        symbol_file: "libz.map.txt",
    },
}

// NDK 导出
ndk_library {
    name: "libz",
    symbol_file: "libz.map.txt",
    first_version: "9",
}

4.2 符号导出 (libz.map.txt)

复制代码
LIBZ {
  global:
    adler32;
    adler32_combine;
    compress;
    compress2;
    compressBound;
    crc32;
    crc32_combine;
    deflate;
    deflateBound;
    deflateCopy;
    deflateEnd;
    deflateInit2_;
    deflateInit_;
    deflateParams;
    deflatePending;
    deflatePrime;
    deflateReset;
    deflateResetKeep;
    deflateSetDictionary;
    deflateSetHeader;
    deflateTune;
    get_crc_table;
    gzbuffer;
    gzclearerr;
    gzclose;
    gzdirect;
    gzdopen;
    gzeof;
    gzerror;
    gzflush;
    gzgetc;
    gzgets;
    gzoffset;
    gzopen;
    gzputc;
    gzputs;
    gzread;
    gzrewind;
    gzseek;
    gzsetparams;
    gztell;
    gzungetc;
    gzwrite;
    inflate;
    inflateBack;
    inflateBackEnd;
    inflateBackInit_;
    inflateCopy;
    inflateEnd;
    inflateGetHeader;
    inflateInit2_;
    inflateInit_;
    inflateMark;
    inflatePrime;
    inflateReset;
    inflateReset2;
    inflateSetDictionary;
    inflateSync;
    uncompress;
    zError;
    zlibCompileFlags;
    zlibVersion;

  local:
    *;
};

4.3 API 版本兼容性

c 复制代码
// zlib.h - Android API 级别兼容性
#if __ANDROID_API__ >= 28
    // API 28+ (Android 9.0): 完整 1.2.13 API
    #define ZLIB_VERSION "1.2.13"
#elif __ANDROID_API__ >= 19
    // API 19-27 (Android 4.4-8.1): 报告为 1.2.8
    #define ZLIB_VERSION "1.2.8"
#else
    // API < 19 (Android < 4.4): 报告为 1.2.6
    #define ZLIB_VERSION "1.2.6"
#endif

// 实际实现版本检测
const char * ZEXPORT zlibVersion(void) {
#if __ANDROID_API__ < 28
    return ZLIB_VERSION;  // 返回兼容版本号
#else
    return ZLIB_VERSION;  // 返回真实版本号
#endif
}

4.4 APEX 模块集成

位置 : com.android.runtime APEX

复制代码
/apex/com.android.runtime/
    lib/
        libz.so           → 系统共享库
    lib64/
        libz.so           → 64 位版本

优势:

  • 独立更新 (无需 OTA)
  • 统一版本 (所有应用共享)
  • 安全修复快速部署

五、性能优化

5.1 编译优化

编译器标志:

python 复制代码
cflags: [
    "-O3",                      // 最高优化级别
    "-fvisibility=hidden",      // 隐藏内部符号
    "-DHAVE_HIDDEN",            // 启用符号可见性控制
    "-DZLIB_CONST",             // const 正确性
    "-ffunction-sections",      // 函数独立段
    "-fdata-sections",          // 数据独立段
]

ldflags: [
    "-Wl,--gc-sections",        // 链接时垃圾回收
]

5.2 算法优化

1. 延迟匹配收益:

复制代码
级别 6 (默认):
  max_lazy_match = 258
  good_match = 32

收益: 压缩率提升 5-15%, 速度降低 20-30%

2. 哈希链限制:

复制代码
级别 1: max_chain = 4      → 快速,低压缩
级别 6: max_chain = 128    → 平衡
级别 9: max_chain = 4096   → 慢速,高压缩

3. Huffman 树选择:

复制代码
动态树: 每个块自适应 (3-5% 压缩率提升)
静态树: 无树开销 (小块 < 1KB 更快)
存储块: 无压缩 (已压缩数据)

5.3 SIMD 性能提升

实测性能 (ARM64):

操作 标量 NEON 提升
Adler-32 500 MB/s 1.8 GB/s 3.6x
CRC-32 (查表) 800 MB/s 1.2 GB/s 1.5x
CRC-32 (CRC32指令) 800 MB/s 4.5 GB/s 5.6x
哈希滑动 250 MB/s 1.5 GB/s 6.0x

实测性能 (x86-64):

操作 标量 SSE/PCLMULQDQ 提升
Adler-32 600 MB/s 2.5 GB/s 4.2x
CRC-32 (折叠) 900 MB/s 8.0 GB/s 8.9x
哈希滑动 300 MB/s 2.0 GB/s 6.7x

5.4 内存访问优化

1. 缓存友好的数据结构:

c 复制代码
// 热路径数据集中在一起
struct internal_state {
    // 经常访问 (L1 cache)
    Bytef *window;
    uInt strstart;
    uInt lookahead;
    uInt ins_h;

    // ... 中间频率

    // 不常访问 (可能 L2/L3)
    ct_data dyn_ltree[HEAP_SIZE];
};

2. 对齐访问:

c 复制代码
// SIMD 要求 16 字节对齐
__m128i *p = (__m128i *)_mm_malloc(size, 16);

3. 预取:

c 复制代码
// 部分实现使用 __builtin_prefetch
__builtin_prefetch(&s->window[s->strstart + MAX_MATCH], 0, 1);

六、测试框架

6.1 单元测试

测试位置 : contrib/tests/

cpp 复制代码
// 示例: infcover.c - inflate 覆盖率测试
void cover_support(void) {
    // 测试工具函数
    assert(zlibVersion() != NULL);
    assert(zlibCompileFlags() != 0);
}

void cover_wrap(void) {
    // 测试 gzip/zlib 包装
    z_stream strm;
    unsigned char in[1], out[1];

    // zlib 格式
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    ret = inflateInit2(&strm, 15);  // windowBits = 15
    assert(ret == Z_OK);

    // gzip 格式
    ret = inflateInit2(&strm, 15 + 16);  // +16 = gzip
    assert(ret == Z_OK);

    // raw DEFLATE
    ret = inflateInit2(&strm, -15);  // 负数 = raw
    assert(ret == Z_OK);
}

void cover_inflate(void) {
    // 测试所有 inflate 状态
    // ... 构造各种边界条件
}

6.2 模糊测试 (Fuzzing)

Android 模糊测试目标:

python 复制代码
// Android.bp - Fuzz 测试
cc_fuzz {
    name: "zlib_deflate_fuzzer",
    srcs: ["contrib/tests/fuzz/deflate_fuzzer.cc"],
    static_libs: ["libz_static"],
}

cc_fuzz {
    name: "zlib_inflate_fuzzer",
    srcs: ["contrib/tests/fuzz/inflate_fuzzer.cc"],
    static_libs: ["libz_static"],
}

cc_fuzz {
    name: "zlib_streaming_inflate_fuzzer",
    srcs: ["contrib/tests/fuzz/streaming_inflate_fuzzer.cc"],
    static_libs: ["libz_static"],
}

cc_fuzz {
    name: "zlib_uncompress_fuzzer",
    srcs: ["contrib/tests/fuzz/uncompress_fuzzer.cc"],
    static_libs: ["libz_static"],
}

Fuzz 测试示例:

cpp 复制代码
// inflate_fuzzer.cc - inflate 模糊测试
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    z_stream strm;
    unsigned char out[65536];

    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;

    // 测试 zlib 格式
    if (inflateInit(&strm) != Z_OK)
        return 0;

    strm.next_in = (unsigned char *)data;
    strm.avail_in = size;
    strm.next_out = out;
    strm.avail_out = sizeof(out);

    // 解压缩 (预期可能失败)
    inflate(&strm, Z_FINISH);

    inflateEnd(&strm);
    return 0;
}

6.3 性能基准测试

位置 : contrib/bench/

c 复制代码
// minigzip.c - gzip 性能测试工具
int main(int argc, char *argv[]) {
    gzFile in, out;
    char buf[BUFLEN];
    int len;
    time_t start, end;

    start = time(NULL);

    in = gzopen(argv[1], "rb");
    out = gzopen(argv[2], "wb9");  // 级别 9

    while ((len = gzread(in, buf, sizeof(buf))) > 0) {
        gzwrite(out, buf, len);
    }

    gzclose(in);
    gzclose(out);

    end = time(NULL);
    printf("Time: %ld seconds\n", end - start);

    return 0;
}

七、最佳实践

7.1 API 使用建议

1. 选择合适的压缩级别

c 复制代码
// ✅ 推荐: 根据场景选择级别
compress2(dest, &destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);  // 级别 6 (平衡)
compress2(dest, &destLen, source, sourceLen, 1);  // 快速压缩
compress2(dest, &destLen, source, sourceLen, 9);  // 最大压缩

// ❌ 不推荐: 总是使用最大压缩 (速度慢 5-10x)
compress2(dest, &destLen, source, sourceLen, 9);  // 除非绝对需要

2. 使用流式 API 处理大文件

c 复制代码
// ✅ 推荐: 流式压缩 (内存友好)
z_stream strm;
deflateInit(&strm, Z_DEFAULT_COMPRESSION);

while (/* 有数据 */) {
    strm.next_in = input_chunk;
    strm.avail_in = chunk_size;

    do {
        strm.next_out = output_buffer;
        strm.avail_out = output_size;

        deflate(&strm, flush);

        write_output(output_buffer, output_size - strm.avail_out);
    } while (strm.avail_out == 0);
}

deflateEnd(&strm);

// ❌ 不推荐: 一次性压缩大文件 (内存爆炸)
unsigned char *huge_buffer = malloc(1GB);
compress(dest, &destLen, huge_buffer, 1GB);  // 可能 OOM

3. 复用 z_stream 对象

c 复制代码
// ✅ 推荐: 复用流对象 (避免重复初始化)
z_stream strm;
deflateInit(&strm, level);

for (int i = 0; i < num_files; i++) {
    deflateReset(&strm);  // 重置状态,保留分配

    // 压缩文件 i
    // ...
}

deflateEnd(&strm);

// ❌ 不推荐: 每次创建新流
for (int i = 0; i < num_files; i++) {
    z_stream strm;
    deflateInit(&strm, level);  // 重复分配 (慢)
    // ...
    deflateEnd(&strm);
}

4. 检查返回值

c 复制代码
// ✅ 推荐: 检查所有返回值
int ret = deflateInit(&strm, level);
if (ret != Z_OK) {
    fprintf(stderr, "deflateInit failed: %d\n", ret);
    return -1;
}

ret = deflate(&strm, Z_FINISH);
if (ret != Z_STREAM_END) {
    fprintf(stderr, "deflate failed: %d\n", ret);
    deflateEnd(&strm);
    return -1;
}

// ❌ 不推荐: 忽略错误
deflateInit(&strm, level);  // 可能失败但未检查
deflate(&strm, Z_FINISH);

7.2 性能优化建议

1. 预分配输出缓冲区

c 复制代码
// ✅ 推荐: 使用 deflateBound 预分配
uLong destLen = deflateBound(&strm, sourceLen);
unsigned char *dest = malloc(destLen);

// ❌ 不推荐: 猜测大小 (可能不够或浪费)
unsigned char *dest = malloc(sourceLen);  // 压缩后可能更大!

2. 批量处理数据

c 复制代码
// ✅ 推荐: 大块处理 (减少函数调用)
#define CHUNK_SIZE (128 * 1024)  // 128 KB
unsigned char in[CHUNK_SIZE];
unsigned char out[CHUNK_SIZE];

while (/* 有数据 */) {
    size_t read = fread(in, 1, CHUNK_SIZE, file);
    strm.next_in = in;
    strm.avail_in = read;
    // ...
}

// ❌ 不推荐: 小块处理 (开销大)
unsigned char in[16];  // 仅 16 字节!
while (fread(in, 1, 16, file)) {
    deflate(&strm, Z_NO_FLUSH);  // 太频繁
}

3. 使用合适的窗口大小

c 复制代码
// 默认 32KB 窗口
deflateInit(&strm, level);

// 小数据: 使用小窗口 (节省内存)
deflateInit2(&strm, level, Z_DEFLATED,
             9,  // windowBits = 9 (512 字节窗口)
             8, Z_DEFAULT_STRATEGY);

// 大文件: 使用大窗口 (更好压缩)
deflateInit2(&strm, level, Z_DEFLATED,
             15,  // windowBits = 15 (32 KB 窗口)
             9,   // memLevel = 9 (更大哈希表)
             Z_DEFAULT_STRATEGY);

7.3 常见陷阱

1. 忘记设置 avail_out

c 复制代码
// ❌ 错误: avail_out = 0,无输出空间
strm.next_out = output;
strm.avail_out = 0;  // 错误!
deflate(&strm, Z_FINISH);  // 立即返回 Z_BUF_ERROR

// ✅ 正确: 提供足够空间
strm.next_out = output;
strm.avail_out = sizeof(output);

2. 使用错误的 flush 模式

c 复制代码
// ❌ 错误: 中途使用 Z_FINISH
while (/* 有数据 */) {
    deflate(&strm, Z_FINISH);  // 错误!只应在最后使用
}

// ✅ 正确: 使用 Z_NO_FLUSH,最后 Z_FINISH
while (/* 有数据 */) {
    deflate(&strm, Z_NO_FLUSH);
}
deflate(&strm, Z_FINISH);  // 最后刷新

3. 混淆格式 (zlib vs gzip vs raw)

c 复制代码
// zlib 格式 (默认)
deflateInit(&strm, level);        // windowBits = 15 (隐式)

// gzip 格式
deflateInit2(&strm, level, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
//                                      ^^^^^^ +16 = gzip 头尾

// raw DEFLATE (无头尾)
deflateInit2(&strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
//                                     ^^^^ 负数 = raw

// 解压缩必须匹配!
inflateInit2(&strm, 15 + 16);  // gzip
inflateInit2(&strm, -15);      // raw

八、与其他库的对比

8.1 zlib vs. LZ4

特性 zlib LZ4
算法 LZ77 + Huffman LZ77 (简化)
压缩率 高 (2-5x) 中 (1.5-2x)
压缩速度 中 (50-100 MB/s) 极快 (500+ MB/s)
解压速度 中 (200-300 MB/s) 极快 (2+ GB/s)
内存使用 中 (256 KB) 低 (64 KB)
场景 通用压缩,网络传输 实时压缩,缓存

8.2 zlib vs. Brotli

特性 zlib Brotli
算法 LZ77 + Huffman LZ77 + 静态字典 + Huffman
压缩率 高 (比 zlib 好 20-30%)
压缩速度 慢 (10x 慢于 zlib)
解压速度 中 (略慢于 zlib)
内存使用 高 (10+ MB)
场景 通用 HTTP 压缩 (WOFF2 字体)

8.3 zlib vs. zstd

特性 zlib zstd
算法 LZ77 + Huffman LZ77 + FSE + 预定义字典
压缩率 高 (比 zlib 好 20-40%)
压缩速度 快 (2-3x zlib)
解压速度 快 (3-4x zlib)
可调性 9 级 22 级 (更细粒度)
场景 传统应用 现代应用,数据库

选择建议:

  • zlib: 兼容性优先,标准格式 (gzip, PNG)
  • LZ4: 速度优先,实时系统
  • Brotli: HTTP 压缩优先
  • zstd: 新项目,需要更好的压缩率和速度平衡

九、总结

9.1 核心优势

1. 标准兼容性

  • RFC 1951 (DEFLATE)
  • RFC 1950 (zlib)
  • RFC 1952 (gzip)
  • PNG, ZIP, HTTP 标准格式

2. 广泛应用

  • APK 压缩 (ZIP)
  • PNG 图像
  • HTTP gzip 传输
  • SQLite 压缩
  • 文件系统压缩

3. 高性能

  • SIMD 优化 (ARM NEON, x86 PCLMULQDQ)
  • 快速路径 (inffast)
  • 缓存友好设计

4. 可移植性

  • 纯 C 实现
  • 最小依赖
  • 跨平台一致

9.2 关键统计

代码规模:

  • 核心代码: 16,000 行 C
  • 头文件: 2,000 行
  • 测试代码: 5,000+ 行
  • Google 扩展: 3,000+ 行 C++

性能指标:

  • 压缩速度: 50-100 MB/s (级别 6)
  • 解压速度: 200-300 MB/s (标量), 500+ MB/s (SIMD)
  • 压缩率: 2-5x (文本), 1.5-2x (二进制)
  • 内存使用: 256 KB (默认)

支持格式:

  • 压缩级别: 0-9
  • 窗口大小: 256 字节 - 32 KB
  • 格式: raw DEFLATE, zlib, gzip

9.3 应用场景

Android 系统:

  • APK 打包/安装
  • PNG 图像解码
  • HTTP gzip 传输
  • SQLite 压缩扩展
  • obb 文件压缩

第三方应用:

  • 文件压缩工具
  • 下载管理器
  • 游戏资源包
  • 数据库备份
  • 日志压缩

相关推荐
熊猫钓鱼>_>5 小时前
【开源鸿蒙跨平台开发先锋训练营】Day 19: 开源鸿蒙React Native动效体系构建与混合开发复盘
react native·华为·开源·harmonyos·鸿蒙·openharmony
向哆哆5 小时前
构建健康档案管理快速入口:Flutter × OpenHarmony 跨端开发实战
flutter·开源·鸿蒙·openharmony·开源鸿蒙
清蒸鳜鱼5 小时前
【Mobile Agent——Droidrun】MacOS+Android配置、使用指南
android·macos·mobileagent
FIT2CLOUD飞致云5 小时前
赛道第一!1Panel成功入选Gitee 2025年度开源项目
服务器·ai·开源·1panel
2501_915918415 小时前
HTTPS 代理失效,启用双向认证(mTLS)的 iOS 应用网络怎么抓包调试
android·网络·ios·小程序·https·uni-app·iphone
向哆哆6 小时前
构建智能健康档案管理与预约挂号系统:Flutter × OpenHarmony 跨端开发实践
flutter·开源·鸿蒙·openharmony·开源鸿蒙
峥嵘life6 小时前
Android EDLA CTS、GTS等各项测试命令汇总
android·学习·elasticsearch
Cobboo6 小时前
i单词上架鸿蒙应用市场之路:一次从 Android 到 HarmonyOS 的完整实战
android·华为·harmonyos
天下·第二6 小时前
达梦数据库适配
android·数据库·adb
定偶6 小时前
MySQL知识点
android·数据结构·数据库·mysql