85 lines
6.1 KiB
Python
85 lines
6.1 KiB
Python
from pathlib import Path
|
||
import hashlib
|
||
import json
|
||
|
||
folder=Path(__file__).parent
|
||
source=json.loads((folder/'source-final.json').read_text(encoding='utf-8'))
|
||
target=json.loads((folder/'target-final.json').read_text(encoding='utf-8'))
|
||
frontend=json.loads((folder/'frontend-results.json').read_text(encoding='utf-8'))
|
||
for result in (source,target):
|
||
assert result['failures']==result['errors']==0
|
||
assert not result['blocked_external_actions']
|
||
before=json.loads((folder/'browser-before.json').read_text(encoding='utf-8'))
|
||
after=json.loads((folder/'browser-final-benchmark.json').read_text(encoding='utf-8'))
|
||
protocol=json.loads((folder/'PROTOCOL_PERFORMANCE.json').read_text(encoding='utf-8'))
|
||
old={row['operation']:row for row in before['measurements']}
|
||
new={row['operation']:row for row in after['measurements']}
|
||
|
||
files=[]
|
||
shared=['wechat_gui_qt.py','wxwork_local_setup.py','wxwork_message_browser.py',
|
||
'assets/ui/console-app.js','assets/ui/zhenyang-ai-console.html',
|
||
'test_database_loading_performance.py','test_wxwork_browser_performance.py']
|
||
extra=['wxwork_protocol_probe.py','wecom_native_sender.py','wxwork_db.py','reply_database.py',
|
||
'wecom_environment.py','test_native_evidence.py','test_protocol_probe_performance.py']
|
||
for root in (Path(r'C:\kefu\wechat_rpa'),Path(r'C:\wechat_rpa')):
|
||
for name in shared+(extra if root==Path(r'C:\wechat_rpa') else []):
|
||
path=root/name;data=path.read_bytes()
|
||
if path.suffix=='.py':compile(data,str(path),'exec')
|
||
files.append({'path':str(path),'sha256':hashlib.sha256(data).hexdigest(),'bytes':len(data)})
|
||
(folder/'final-file-manifest.json').write_text(json.dumps(files,ensure_ascii=False,indent=2),encoding='utf-8')
|
||
switches=[new['switch_'+str(i)]['seconds']*1000 for i in range(1,4)]
|
||
report=f'''# 消息库加载与协议检测优化
|
||
|
||
日期:2026-09-17
|
||
|
||
已更新 `C:\\kefu\\wechat_rpa` 和 `C:\\wechat_rpa` 的共用消息库/界面代码;协议优化仅更新已有协议功能的 `C:\\wechat_rpa`。保留两目录其他差异。
|
||
|
||
## 结果
|
||
|
||
- 本地聊天先显示,远程患者关联单独加载。患者接口超时不再挡住消息列表,且旧会话的迟到结果不会覆盖当前会话。
|
||
- 加载期间保留最后一次切账号、切会话与搜索;患者关联请求最多一个执行中加一个最新待办,避免堆积。
|
||
- 缓存文件信息、联系人名称、统计及会话行号;切换只读所需消息页。显式刷新、数据库/WAL变化、文件替换会使缓存失效;取行时核对会话,防止文件替换竞争导致串消息。
|
||
- 消息库旧会话搜索不再受最近1000会话的限制。
|
||
- 协议健康检测只准备当前账号的 `message.db`,不再初始化其他历史账号及联系人表。实际回复仍加载需要的元数据。
|
||
- 同轮只读协议检测复用大文件构建哈希;新进程、文件变化、下一轮检测、实际发送仍重新校验。保留当前账号和发送入口检查,没有缓存登录就绪判断。
|
||
- 协议检测和消息库同时请求密钥时共用一次进行中的读取;完成后再次主动获取仍执行新校验。
|
||
- 去掉重复刷新、重复选择;中文输入法仅搜索最终文字,加载时保留搜索焦点与光标。协议检测实际耗时写入运行日志。
|
||
|
||
## 测量
|
||
|
||
以下均为临时合成数据与组件测量,不是线上端到端保证。
|
||
|
||
| 测量范围 | 优化前 | 优化后 |
|
||
|---|---:|---:|
|
||
| 50万消息、2500会话,首次打开本地浏览模型 | {old['cold_open']['seconds']:.3f} 秒 | {new['cold_open']['seconds']:.3f} 秒 |
|
||
| 同样数据,重复切换会话 | 1.297–1.394 秒 | {min(switches):.1f}–{max(switches):.1f} 毫秒 |
|
||
| 搜索旧会话 | 1.341 秒且漏查 | {new['search_old_conversation']['seconds']*1000:.1f} 毫秒,正确返回 |
|
||
| 4账号、24库、6万联系人:协议数据库准备 | 1708.684 毫秒 | 22.029 毫秒 |
|
||
| 64 MiB构建文件,同轮两次完整哈希校验 | 255.550 毫秒 | 149.119 毫秒 |
|
||
| 连点刷新/检测5次 | 5次界面调用 | 1次 |
|
||
|
||
在另一个控制实验中,仅模拟患者接口延迟300毫秒,本地结果等待由约301毫秒降至不到1毫秒;这是解除网络等待的验证,不包含真实数据库读取成本。
|
||
|
||
首次没有可用密钥时仍需本机初始化,数据库或WAL变化后也需要重建受影响缓存。这些必要工作没有被跳过。
|
||
|
||
原始数据:[本地浏览最终基准](browser-final-benchmark.json)、[优化前](browser-before.json)、[协议组件基准](PROTOCOL_PERFORMANCE.json)、[网络等待控制实验](local-first-target-benchmark.json)。
|
||
|
||
## 验证
|
||
|
||
- 原版目录:{source['tests_run']-source['skipped']}项通过、{source['skipped']}项协议能力不适用跳过、0失败。
|
||
- 协议目录:{target['tests_run']-target['skipped']}项通过、0失败。
|
||
- 两目录界面交互:15项通过、JavaScript错误0;合成截图已检查。
|
||
- 覆盖缓存失效、WAL、账号隔离、数据库替换竞争、协议构建变化、当前账号健康检查、旧审核入口及归档模拟传输。
|
||
- 所有验证使用隔离数据与模拟服务,没有发送真实聊天、注入真实进程或改动真实队列、密钥和数据库。
|
||
|
||
结果:[原版](source-final.json)、[协议版](target-final.json)、[界面](frontend-results.json)。中间测试中的请求被隔离器拦截,是模拟传输层位置问题;最终隔离器继续阻止真实网络,上述最终回归全部通过。
|
||
|
||
## 使用与回滚
|
||
|
||
当前运行的是 Python 源码客户端,重新启动对应目录的客户端即可加载优化。未主动终止或重启当前程序,未重新制作安装包。
|
||
|
||
源码备份位于两个目录的 `backups/loading-performance-20260917`,前端位于其 `frontend` 子目录。当前变更文件及SHA256见[清单](final-file-manifest.json)。回滚时只恢复对应代码文件,勿覆盖真实数据与登录配置。
|
||
'''
|
||
(folder/'TEST_REPORT.md').write_text(report,encoding='utf-8')
|
||
print(json.dumps({'report':str(folder/'TEST_REPORT.md'),'files':len(files),'source_passed':source['tests_run']-source['skipped'],'target_passed':target['tests_run']-target['skipped']},ensure_ascii=False))
|