疑似的内存溢出问题(?)
检查项
- [x] 我确认此问题在所有分支的最新版本中依旧存在
- [x] 我确认在 Issues 列表中并无其他人已经提出过与此问题相同或相似的问题
- [ ] 我使用了 Docker
使用的分支
main
具体版本号
0.10.3
遇到的问题
我在2g内存的linux服务器上部署的本程序,除了本程序和napcat以外没有其它额外进程。经常出现内存占满而进程被kill的情况,只能从后台重新启动。据观察发现,本程序并不会一开始就沾满内存,而是随着运行时间占用内存不断增加,最后到达阈值被kill,因此怀疑是内存泄漏问题。
报错信息
如何重现此问题?
启动后正常运行即可,无需特别操作。需要注意的是这个问题并非这个版本独有,从较早的版本就已经存在,但是目前的版本似乎尤为严重。
可能造成问题的原因
No response
系统环境
Ubuntu Server 24.04 LTS
Python 版本
Python 3.11
补充信息
No response
我自己部署的麦麦运行了一个多月了,运行在4GB内存的机器上,没有观察到过内存泄漏的问题。能确定是麦麦占用的内存吗?感觉需要更多详细信息来分析。
我自己部署的麦麦运行了一个多月了,运行在4GB内存的机器上,没有观察到过内存泄漏的问题。能确定是麦麦占用的内存吗?感觉需要更多详细信息来分析。
我没有运行其它任何程序,而且一旦被kill之后内存占用就回复初始状态了
你使用top或类似的命令检查过吗?确定是Python进程导致的异常内存占用么?
如果真的是Python导致的异常占用,不妨更换升级一下Python版本,也许是你使用的某个特定的Python版本触发了罕见的溢出问题?
我在我的2G内存的Linux服务器上部署过更早的版本,大概是0.6时期,那时候甚至还没有脱离MongoDB,即使如此也从没遇到过内存溢出的情况。
现在在4G的Windows上部署最新的dev版本,同样也没有遇到过这种情况。
此外,问个不相关的,你应该没有使用VSCode的Remote-SSH访问服务器吧?它的服务端比较吃内存。
如果实属疑难杂症,可以尝试使用docker容器化部署,顺便一提,对于2G低内存的机器,推荐开启zram来缓解内存压力。
你使用top或类似的命令检查过吗?确定是Python进程导致的异常内存占用么?
如果真的是Python导致的异常占用,不妨更换升级一下Python版本,也许是你使用的某个特定的Python版本触发了罕见的溢出问题?
我在我的2G内存的Linux服务器上部署过更早的版本,大概是0.6时期,那时候甚至还没有脱离MongoDB,即使如此也从没遇到过内存溢出的情况。
现在在4G的Windows上部署最新的dev版本,同样也没有遇到过这种情况。
此外,问个不相关的,你应该没有使用VSCode的Remote-SSH访问服务器吧?它的服务端比较吃内存。
如果实属疑难杂症,可以尝试使用docker容器化部署,顺便一提,对于2G低内存的机器,推荐开启zram来缓解内存压力。
这是zram的占用情况,已经吃了5.4G的zram了,比我MC服务器占用还大 以及这就是docker容器化部署的服务
你使用top或类似的命令检查过吗?确定是Python进程导致的异常内存占用么?
如果真的是Python导致的异常占用,不妨更换升级一下Python版本,也许是你使用的某个特定的Python版本触发了罕见的溢出问题?
我在我的2G内存的Linux服务器上部署过更早的版本,大概是0.6时期,那时候甚至还没有脱离MongoDB,即使如此也从没遇到过内存溢出的情况。
现在在4G的Windows上部署最新的dev版本,同样也没有遇到过这种情况。
此外,问个不相关的,你应该没有使用VSCode的Remote-SSH访问服务器吧?它的服务端比较吃内存。
如果实属疑难杂症,可以尝试使用docker容器化部署,顺便一提,对于2G低内存的机器,推荐开启zram来缓解内存压力。
我在我的服务器上使用Docker部署时也遇到了疑似内存溢出的问题,查看占用情况主要是core的容器在吃内存
刚启动时Core占用 ~300MB,运行大概 5-6 个小时后占用 ~900MB
我的服务器运行MaiBot有一个很奇怪的症状 直接运行bot.py cpu占用高且经常爆内存 但是如果以服务运行 就没事 命令行参数 环境变量和用户都是一模一样的 cursor agent检查没有发现任何问题
最新的0.11.5版本也有该问题,我也提出了issue,以下是deepwiki的分析 根据我对代码库的分析,我找到了导致内存泄漏的主要原因:
主要问题:last_messages 字典无限增长
在 ChatManager 类中,存在一个名为 last_messages 的字典,用于存储每个聊天流的最后一条消息。 1
每次收到消息时,register_message 方法都会将消息添加到这个字典中: 2
关键问题是:这个字典中的消息从未被清理或删除。随着机器人运行时间的增长,每个新的 stream_id 都会在字典中添加一个条目,并且这些条目会永久保留在内存中。
内存泄漏的影响
在 bot.py 中,每次处理消息时都会调用 register_message: 3
这意味着:
- 每个活跃的聊天流(群组或私聊)都会在
last_messages中保留一条消息 - 如果机器人在大量群组中活跃,或处理大量私聊,这个字典会持续增长
MessageRecv对象本身可能包含大量数据(消息内容、用户信息、上下文等)- 没有任何机制来限制字典的大小或清理旧条目
与数据库清理的对比
虽然项目中有 MemoryForgetTask 来定期清理数据库中的旧聊天历史记录, 4
但这个任务只清理数据库中的记录,不会清理内存中的 last_messages 字典。
解决建议
要解决这个内存泄漏问题,需要实现以下机制之一:
- 限制字典大小:使用
collections.deque并设置maxlen参数,或实现 LRU 缓存 - 定期清理:添加定时任务,删除长时间未活跃的聊天流的消息
- 使用弱引用:考虑使用
weakref来存储消息引用 - 设置过期时间:为每条消息添加 TTL(生存时间),定期清理过期消息
Notes
- 这个问题在高活跃度的机器人实例中会更快地显现,特别是在 Debian 12 这样的长期运行的服务器环境中
- 内存泄漏是渐进式的,所以可能需要运行一段时间后才会导致系统崩溃
- 虽然代码中有数据库层面的记忆遗忘机制,但内存中的数据结构缺乏相应的清理逻辑
- 建议开发者在
ChatManager类中添加定期清理机制,或限制last_messages和streams字典的大小
Citations
File: src/chat/message_receive/chat_stream.py (L130-130)
self.last_messages: Dict[str, "MessageRecv"] = {} # stream_id -> last_message
File: src/chat/message_receive/chat_stream.py (L162-170)
def register_message(self, message: "MessageRecv"):
"""注册消息到聊天流"""
stream_id = self._generate_stream_id(
message.message_info.platform, # type: ignore
message.message_info.user_info,
message.message_info.group_info,
)
self.last_messages[stream_id] = message
# logger.debug(f"注册消息到聊天流: {stream_id}")
File: src/chat/message_receive/bot.py (L282-282)
get_chat_manager().register_message(message)
File: src/chat/utils/memory_forget_task.py (L17-22)
class MemoryForgetTask(AsyncTask):
"""记忆遗忘任务,每5分钟执行一次"""
def __init__(self):
# 每5分钟执行一次(300秒)
super().__init__(task_name="Memory Forget Task", wait_before_start=0, run_interval=300)
@rfatfsg
请给出能够复现内存泄漏现象的流程,或者置信度高的内存泄露证据以供开发人员排查,不然修复工作难以入手
才看到这个旧 issue,虽然没能确定原因而且可以排除 last_messages 的问题,但还是尝试修了一下 ChatManager 个人觉得虽然大概率不是泄漏了,但是非要找问题有可能是多次初始化循环的后台协程导致的内存缓慢上涨(?
我在我ubuntu服务器运行也是同样情况 内存占满后疑似kernel panic杀死了进程 但是只要将/path/to/venv/bin/python bot.py命令行 用同样环境变量 同样用户 做成服务启动 就不会占这么多内存了 我不理解为什么 但是实际确实是这样... 至少在我的服务器上是可以这样解决的(
我在我ubuntu服务器运行也是同样情况 内存占满后疑似kernel panic杀死了进程 但是只要将/path/to/venv/bin/python bot.py命令行 用同样环境变量 同样用户 做成服务启动 就不会占这么多内存了 我不理解为什么 但是实际确实是这样... 至少在我的服务器上是可以这样解决的(
最新的11.6版本仍然有内存不断上涨的问题,作者回复了不是我上述AI分析的原因,现在究竟是什么问题导致的仍然不知道,我的服务器是Debian13,4c8g,现在一天左右的时间就会把我的内存占满致使崩溃,我必须要手动重启一遍程序才能把内存降下来