Files
pj_supermarket_cloud/docs/face-startup-performance.md
T
dzc 7c20242ad7 perf: optimize face library startup and differential sync
Stream and validate native feature loading with fast decoding and bounded SDK batches.
Reconcile authoritative department snapshots with rollback-safe metadata and file updates.
Bound downloads, isolate duplicate identifiers, and defer unchanged invalid photo versions.
Remove unused legacy face APIs and document device measurements.

Validation: 42 Flutter tests in an isolated source snapshot; native unit and device checks;
all 5,537 registered features verified byte-for-byte, plus real SDK photo searches and metadata checks.
2026-10-22 16:35:52 +08:00

80 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 人脸库启动装载优化与真机验证
验证日期:2026-10-22。设备:RK3568,Android 11。实际业务库包含 5,537 条人脸,每条特征 2,056 字节,无缺失或损坏特征。
## 改动
- 原生读取改为 `id > ? AND id <= ? ORDER BY id LIMIT 128`,只选择装库字段,复用一个数据库连接。记录开始时的数量和最大主键,结束时校验读取数量。
- 标准整数 JSON 数组直接解码到一次分配的 `byte[]`,兼容 Java 有符号字节、Flutter 无符号字节;合法历史数字形式由 JsonReader 兼容解析。拒绝越界、溢出、损坏和多余尾部数据。
- 读取和注册交替执行,注册批次采用 1,000 条,避免先在 Java 中物化整库特征再开始注册。
- 每 150 ms 合并同阶段进度,阶段切换和结束立即发送;load 页显示实际阶段与处理数量。
- 缺失/损坏特征逐条从原图片修复,按页提交修复事务,不再每张图片打开数据库并单独提交。
- SDK 批次失败时清理可能的部分写入后进行二分隔离;清理失败立即中止。非法或重复搜索标识计为失败,禁止截断标识或覆盖其他用户的在库标识。
- 虹软空库清空按幂等成功处理;结束时同时核对读取行数、成功/失败数量、SDK 数量及业务映射数量。数据库错误不返回成功的前缀结果。
- 启动完成整库读取与修复后,收尾仅查询空特征记录,统一处理 NULL、空串、`[]`、`null`;不再把全部轻量档案传回 Dart 筛选。
- 增加 `FaceStartupPerf` 脱敏汇总日志和结果 metrics,区分读库、解析、修复、引擎初始化、注册以及 Dart 激活/清理耗时。
沿用数据库 v15 和原有 JSON 特征存储格式,无数据库迁移。SDK 激活参数校验及原有人脸互斥队列继续复用。
## 受控 A/B 结果
同一 Debug APK、同一台设备和同一份数据,每组 3 轮,每轮重新初始化虹软引擎。旧算法仅在测试 APK 中保留用于对照;不会把旧实现带入正式包。
| 方案 | 三轮装库耗时 / ms | 中位数 / ms | 注册调用数 |
| --- | --- | --- | --- |
| 旧 SELECT *、每条 Gson、每批 100 | 11996 / 11418 / 11387 | 11418 | 56 |
| 优化读取/解析,每批 100 | 3929 / 3841 / 3871 | 3871 | 56 |
| 优化读取/解析,每批 500 | 3590 / 3516 / 3545 | 3545 | 12 |
| 优化读取/解析,每批 1000 | 3560 / 3467 / 3473 | 3473 | 6 |
采用 1,000 条批次后,中位数下降约 69.6%,约为旧算法的 3.29 倍速度。主要收益来自读取及解析;批次调整贡献约 0.4 秒。
最终方案三轮分段耗时:读库约 1.29–1.32 秒,解析约 1.21–1.22 秒,SDK 注册约 0.68–0.70 秒,引擎初始化约 0.25 秒;每轮只有 22 次进度事件。
独立测试不启动 Flutter UI,也不包含旧版逐条进度发送,因此与实际 App 冷启动区分记录。优化前实际 App 日志中,读库/解析约 14.29 秒,从开始查询到装库完成约 17.87 秒。原生 `durationMs` 不包含 Dart 中的 SDK 激活和收尾清理,完整人脸准备耗时由 `startupMs` 记录。
## 正确性与回归
- 每组每轮均成功注册 5,537 条,失败 0 条;核对全部样本标识集合,并逐条从 SDK 取出特征与优化前 Gson 读取的字节比较。
- 从本地四张实际照片生成 `ExtractType.RECOGNIZE` 查询特征,每轮检索均匹配到正确用户。SDK 区分注册特征和查询特征,不能直接使用 REGISTER 特征作查询。
- 原生解析单元测试 3 项通过,包含随机特征及全部字节边界、历史空值、兼容数字形式、畸形/越界/长数字溢出等输入。
- 真机独立内存 SQLite 11 项断言通过:分页边界、坏 JSON 后续行不丢失、标识溢出、修复落库、用户范围、快照上界、读取期间删除导致的不完整检测。
- 模拟 SDK 部分写入后的失败隔离及清理失败中止 2 项断言通过。1,024 条中单个坏样本不会退化为整批逐条重试;不向实际业务库或真实 SDK 注入坏特征。
- 最终提交的独立源码副本共 42 项 Flutter 测试通过(原有 15 项及本次新增 27 项)。
- Flutter 静态分析无 error。原有 66 条 warning/info 之外,新增两个 Floor `IN` 查询产生 4 条生成代码风格提示,业务源代码没有新增提示。
最终 Release 实际 App 原生装库测得 4,315 ms,5,537 条全部成功、失败 0。启动优化阶段首次快照逐行核对已存人脸 id、sampleId、userId 和 faceModel,全部不变;数据库 v15 完整性检查正常,首次快照的订单及挂单数量不变。后续同步测试期间的完整数据核对见 face-sync-reliability.md。Release 不输出 Dart info 级控制台日志,原生 FaceStartupPerf 仍可从 adb 读取。
最新原生回归装库 3,584 ms;另有 2 项真实 SDK 元数据更新/整批拒绝断言通过,不重写特征或业务数据库。
以上验证覆盖装库、字节一致性和基于本地照片的 SDK 检索;真人摄像头活体识别与实际支付需独立验收。
## 复测
使用 Flutter 3.27.4、JDK 17。原生测试入口只存在于 androidTest APK,不在发布包中。
```sh
# 仓库根目录
fvm flutter test --no-pub
fvm flutter analyze --no-pub --no-fatal-infos --no-fatal-warnings
# android 目录
./gradlew :app:testDebugUnitTest :app:assembleDebug :app:assembleDebugAndroidTest
adb install -r ../build/app/outputs/apk/debug/app-debug.apk
adb install -r ../build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk
# 仅独立 SQLite 和 SDK 失败隔离检查
adb shell am instrument -w -r \
com.example.pj_supermarket_cloud.test/io.flutter.plugins.facediscern.flutter.FaceStartupInstrumentation
# 真实数据 A/B:要求本机 SDK 已激活,所有样本已有完整特征和对应照片
adb shell am instrument -w -r -e benchmark true -e mode optimized -e batch 1000 -e rounds 3 \
com.example.pj_supermarket_cloud.test/io.flutter.plugins.facediscern.flutter.FaceStartupInstrumentation
# 旧算法对照,或调整 batch 为 100 / 500
adb shell am instrument -w -r -e benchmark true -e mode legacy -e rounds 3 \
com.example.pj_supermarket_cloud.test/io.flutter.plugins.facediscern.flutter.FaceStartupInstrumentation
```
测试不启动收银页面,不发起支付或远端人脸同步;照片只读,输出仅包含耗时、计数和通过状态。装库前需保留现有 APK 与数据库备份,使用 `adb install -r` 保留应用数据。