问题说明
项目地址:musnows/encrypt2bdy
之前自己瞎写了一个上传文件到百度云的python程序,提供了docker并部署在了我自己的nas上,但是我限制容器可用内存大小为1GB后,总是会遇到docker因为内存爆满直接被系统kill了的情况。
现在总算有时间看看到底是啥问题了,其实我已经能想到了,上传文件的部分已经是按分片上传的,理论上不是那个地方的问题,另外一个打开文件的地方只有一处,就是计算文件整体md5的操作。
因为当时没想明白问题在哪里,我还在项目的README里面写了一个不建议用于备份大文件,因为内存会撑爆的提示(
1 2 3 4 5 6 7
| ## 已知错误
### 1.docker退出码137
内存不足时,系统将对应docker容器终止。出现此问题,请确认您要备份的文件中不会出现大于您系统内存或docker容器内存限制的文件。
正如开头所说,本项目适合于备份照片、图片、文档等小文件,并不建议用于备份录像、电影等资源。
|
原有代码读取md5的方式
在程序中,我计算文件整体md5的操作是这样写的
1 2 3 4 5 6 7
| with open(file_path, 'rb') as f: file_bytes = f.read()
file_name = os.path.basename(file_path) file_md5_str = hashlib.md5(file_bytes).hexdigest() _log.debug(f"{file_path} | {file_md5_str}")
|
问题其实很明朗,就是这里的f.read()
操作直接将整个文件加载到内存里面了!备份的文件稍微大一点,指定要把内存整爆的!
分片读取md5
这部分代码应该替换为如下形式,分片读取文件,并将读取的md5给update到hashlib.md5()
对象中
1 2 3 4 5 6 7 8
| def file_md5(file_path: str): """给定一个文件路径,分片加载文件,计算文件的md5""" chunk_size = 4096 with open(file_path, 'rb') as f: file_md5 = hashlib.md5() while chunk := f.read(chunk_size): file_md5.update(chunk) return file_md5.hexdigest()
|
经过测试,这种办法计算出来的md5和直接f.read()
全部计算出的md5完全一致
1 2 3
| ╰─ python3.10 test.py ca60e24bf4dde156a381c8b9d268faf5 ca60e24bf4dde156a381c8b9d268faf5
|
内存占用监控线程
用下面的代码弄个内存占用的监控线程,通过psutil库实时打印内存占用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import psutil import os import threading import time
def monitor_memory_usage(): process = psutil.Process(os.getpid()) while True: memory_info = process.memory_info() print(f"Memory used: {memory_info.rss / (1024 * 1024):.2f} MB") time.sleep(1)
memory_monitor_thread = threading.Thread(target=monitor_memory_usage) memory_monitor_thread.start()
memory_monitor_thread.join()
|
内存占用测试
将项目中上传到百度云的部分注释掉,休眠10秒替代上传操作,模拟原有代码整体打开一个文件,又分片打开文件上传到百度云的流程。
用两个450MB左右的视频做测试。程序原有思路是遍历需要备份目录中的所有文件,分片上传到百度云。计算整个文件的MD5的操作其实是用来本地入库标定文件是否有修改、是否已经上传的。
不过后续加密文件的操作也是无脑f.read()
,这部分也需要修改。
日志输出如下,可以看到,开始处理test目录之后,程序直接把视频完整加载到了内存里面,占用内存的大小和视频文件大小基本一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| ╰─ python3.10 main.py [23-12-17 20:01:22] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml' [23-12-17 20:01:22] INFO:confLoad.py:<module>:89 | [config] loaded config success [23-12-17 20:01:22] INFO:querySql.py:<module>:72 | [sqlite3] create all tables [23-12-17 20:01:23] INFO:main.py:<module>:294 | [start] start at 23-12-17 20:01:23 [23-12-17 20:01:23] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key' Memory used: 39.18 MB [23-12-17 20:01:23] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 20:01:23 [23-12-17 20:01:23] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2 [23-12-17 20:01:23] INFO:main.py:upload_task:144 | [0] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB Memory used: 483.52 MB [23-12-17 20:01:33] INFO:main.py:upload_task:237 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca [23-12-17 20:01:33] INFO:main.py:upload_task:144 | [1] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB Memory used: 517.39 MB [23-12-17 20:01:44] INFO:main.py:upload_task:237 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71 [23-12-17 20:01:44] INFO:main.py:upload_task:282 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2 [23-12-17 20:01:44] INFO:main.py:upload_task:283 | 本次上传完毕,平均上传速度:43.143mb/s | 总耗时:21.16s [23-12-17 20:01:44] INFO:main.py:upload_task:286 | 本次上传完毕,下次处理:2023-12-17 21:00:00
|
带上加密之后更加离谱,只是第一个文件就直接把内存占用干到了3.2GB,处理第二个文件的时候,也是直接干到了2.4GB,这种程度的内存消耗谁顶得住?更何况百度云API最大支持10GB的文件上传,如果要加载一个10GB的文件还得了啊?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| ╰─ python3.10 main.py [23-12-17 19:43:56] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml' [23-12-17 19:43:56] INFO:confLoad.py:<module>:89 | [config] loaded config success [23-12-17 19:43:56] INFO:querySql.py:<module>:72 | [sqlite3] create all tables [23-12-17 19:43:56] INFO:main.py:<module>:291 | [start] start at 23-12-17 19:43:56 Memory used: 39.31 MB [23-12-17 19:43:56] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key' [23-12-17 19:43:56] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 19:43:56 [23-12-17 19:43:56] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2 Memory used: 923.04 MB Memory used: 3267.48 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB Memory used: 483.71 MB [23-12-17 19:44:08] INFO:main.py:upload_task:234 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca Memory used: 990.96 MB Memory used: 2410.97 MB Memory used: 1622.17 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB Memory used: 517.57 MB [23-12-17 19:44:22] INFO:main.py:upload_task:234 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71 [23-12-17 19:44:22] INFO:main.py:upload_task:279 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2 [23-12-17 19:44:22] INFO:main.py:upload_task:280 | 本次上传完毕,平均上传速度:35.371mb/s | 总耗时:25.81s [23-12-17 19:44:22] INFO:main.py:upload_task:283 | 本次上传完毕,下次处理:2023-12-17 21:00:00
|
先将md5计算的函数给修改了,改成分片计算。可以看到,效果显著!内存占用和程序刚开始运行的时候差距只有5MB,这才是正常的内存占用!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| ╰─ python3.10 main.py [23-12-17 20:03:20] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml' [23-12-17 20:03:20] INFO:confLoad.py:<module>:89 | [config] loaded config success [23-12-17 20:03:20] INFO:querySql.py:<module>:72 | [sqlite3] create all tables [23-12-17 20:03:20] INFO:main.py:<module>:294 | [start] start at 23-12-17 20:03:20 Memory used: 39.26 MB [23-12-17 20:03:20] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key' [23-12-17 20:03:20] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 20:03:20 [23-12-17 20:03:20] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2 [23-12-17 20:03:20] INFO:main.py:upload_task:144 | [0] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB [23-12-17 20:03:32] INFO:main.py:upload_task:237 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca [23-12-17 20:03:32] INFO:main.py:upload_task:144 | [1] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB Memory used: 44.08 MB [23-12-17 20:03:44] INFO:main.py:upload_task:237 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71 [23-12-17 20:03:44] INFO:main.py:upload_task:282 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2 [23-12-17 20:03:44] INFO:main.py:upload_task:283 | 本次上传完毕,平均上传速度:38.689mb/s | 总耗时:23.60s [23-12-17 20:03:44] INFO:main.py:upload_task:286 | 本次上传完毕,下次处理:2023-12-17 21:00:00
|
The end
关于分片计算md5的介绍就这么多,我这个程序里面文件加密的部分也需要修改,不过那就不是本文的范畴了~