Python 内存优化问题

2023-04-11 19:01:31 +08:00
 ChenJHua

我发现 import pymongo 就会占用 6M 内存。 我有 100 个独立运行的脚本,如果他们都需要 import pymongo ,那么就会产生 100*6=600M 内存。 可以实现一个 import 缓存,独立运行的脚本都可以优先复用缓存的包,缓存没有才重新导包。 想问问这个 import 缓存能实现吗

4232 次点击
所在节点    Python
59 条回复
maocat
2023-04-11 19:06:56 +08:00
按需加载 from pymongo import xxx
yingxiangyu
2023-04-11 19:16:20 +08:00
独立运行没办法共享吧,如果是直接用多进程应该是可以共享的
passerby233
2023-04-11 19:19:37 +08:00
duke807
2023-04-11 19:21:35 +08:00
你试了没有?确定不同进程 import 同一个库,该库的可执行代码的部分没有共用?
ChenJHua
2023-04-11 19:44:00 +08:00
@maocat 尝试了一下,__init__.py 里面就 import 了所有了,从 pymongo 导部分东西也会占用这么大
ChenJHua
2023-04-11 19:44:16 +08:00
@yingxiangyu 这样对我的改动太大了,太多脚本了
ChenJHua
2023-04-11 19:44:32 +08:00
@duke807 不共用的,试过了
ClericPy
2023-04-11 19:46:22 +08:00
麻烦, 自己倒腾个 ipc 算了, 就几行原生代码, 我是照抄官网的 asyncio 和 struct 自己搭个 Unix domain socket 就完事了, 你这情况都用不着这么复杂, 我那是抗上万并发用的
ChenJHua
2023-04-11 19:46:47 +08:00
@passerby233 感谢你的帮助,这种只能对同一个脚本生效。无法满足我的需求
ChenJHua
2023-04-11 19:50:42 +08:00
@ClericPy 不太明白这和 IPC 有啥关系。我这边尝试初始化了一片共享内存出来,import pymongo 想保存到共享内存里面需要序列化,其他地方要想复用需要从共享内存序列化回来,但是序列化回来后还是会占用 6M 内存
Varchar
2023-04-11 19:58:45 +08:00
可以通过使用 Python 的 importlib 和 sys 模块来实现 import 缓存。可以将已经导入的模块对象存储在一个字典中,每次导入模块时先检查该字典中是否已经存在该模块对象,如果存在则直接使用该对象,否则重新导入并将导入结果存储到字典中。以下是一个简单的实现示例:

```python
import importlib
import sys

module_cache = {}

def import_module(module_name):
if module_name in module_cache:
return module_cache[module_name]
module = importlib.import_module(module_name)
module_cache[module_name] = module
return module

# 使用示例
pymongo = import_module('pymongo')
```

使用该 import_module 函数代替直接导入 pymongo 模块即可实现 import 缓存。

以上答案来自于 deflash.ai. 😄
Varchar
2023-04-11 19:59:16 +08:00
我没尝试啊,能不能用,楼主自己试。
ClericPy
2023-04-11 20:08:39 +08:00
@ChenJHua 就是不直接使用 pymongo 对象, 改远程调用或者跨进程... 那个对象本来就一大堆内置方法, 内存省不了多少的, 做个 HTTP 的接口封装一下也行. 一般情况下脚本都不允许直连数据库, 你们可能要求不严格.

其实我说的就是走远程过程调用相关的事情, 有点跑题了.

你一百个脚本走一百个进程, 实际上 python 解释器运行时候 builtins 也占用 20 多 MB 了, 节省那 6MB 实际意义不大, 缓存的包你跨进程没法共享, 你说的序列化什么的实际上又新建了一遍对象. 这些脚本可以考虑从多进程转到多线程里面, 就可以共享连接池了.

现在看到一大堆脚本就头疼, 刚换的工作掉进脚本地狱里了, 所有东西都面向过程毫无抽象逻辑, 怀念有 azkaban 管理的上一份工作
ChenJHua
2023-04-11 20:28:54 +08:00
@Varchar 谢谢大佬,这个是单脚本适用,多脚本就适用不了了
ChenJHua
2023-04-11 20:30:24 +08:00
@ClericPy 明白你意思了,但是我改不动,走远程过程调用改动太大了。我也头秃,现在要做内存优化,抠到极致了,只能抠这个了,多线程或者多进程对我改动也很大,所以比较头秃
ClericPy
2023-04-11 20:38:43 +08:00
@ChenJHua 我之前把东西跑 hadoop 上也天天优化内存, 你这优化个 6MB 就很伪需求了... Serverless 一般最小规格都 128MB 了, pymongo 导入就这么大, 用精确导入具体对象的方式呢? 然后手动 gc.collect 什么的. 真抠啊
akira
2023-04-11 21:43:24 +08:00
你同时跑 100 个进程也要能跑的过来才行吧。。与其在内存这么抠,还不如看下怎么更合理的调度,降低同时跑的数量
whitewinds
2023-04-12 00:21:24 +08:00
你 100 个独立脚本,运行就要 100 个 python 解释器进程,进程之间内存隔离。或者你单独起一个 pymongo 的服务进程,其他脚本进程用 IPC 调它。
009694
2023-04-12 00:40:07 +08:00
大家提了这么多方法,op 就只一句话:没法改。 既然没法改那优化什么内存啊😂
omgr
2023-04-12 08:03:48 +08:00
一句话,这么在意内存占用就 RIIR ( x

- 考虑性价比,内存白菜价了,时间和人力成本更贵,真不够不如加内存
- 解决需要 100 个独立脚本的问题
- 使用 memray 找到短板,6M 的 pymongo 真的是大头吗,先上 python3.11 看看

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/931691

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX