MaiBot icon indicating copy to clipboard operation
MaiBot copied to clipboard

Maibot内存泄露问题

Open rfatfsg opened this issue 1 month ago • 0 comments

检查项

  • [x] 我确认此问题在所有分支的最新版本中依旧存在
  • [x] 我确认在 Issues 列表中并无其他人已经提出过与此问题相同或相似的问题
  • [ ] 我使用了 Docker

使用的分支

main

具体版本号

0.11.5

遇到的问题

在Debian12系统中,主程序会不断占用内存直至系统内存被塞满导致程序崩溃,下方报错信息为deepwiki的分析

报错信息

根据我对代码库的分析,我找到了导致内存泄漏的主要原因:

主要问题:last_messages 字典无限增长

ChatManager 类中,存在一个名为 last_messages 的字典,用于存储每个聊天流的最后一条消息。 1

每次收到消息时,register_message 方法都会将消息添加到这个字典中: 2

关键问题是:这个字典中的消息从未被清理或删除。随着机器人运行时间的增长,每个新的 stream_id 都会在字典中添加一个条目,并且这些条目会永久保留在内存中。

内存泄漏的影响

bot.py 中,每次处理消息时都会调用 register_message3

这意味着:

  • 每个活跃的聊天流(群组或私聊)都会在 last_messages 中保留一条消息
  • 如果机器人在大量群组中活跃,或处理大量私聊,这个字典会持续增长
  • MessageRecv 对象本身可能包含大量数据(消息内容、用户信息、上下文等)
  • 没有任何机制来限制字典的大小或清理旧条目

与数据库清理的对比

虽然项目中有 MemoryForgetTask 来定期清理数据库中的旧聊天历史记录, 4

但这个任务只清理数据库中的记录,不会清理内存中的 last_messages 字典。

解决建议

要解决这个内存泄漏问题,需要实现以下机制之一:

  1. 限制字典大小:使用 collections.deque 并设置 maxlen 参数,或实现 LRU 缓存
  2. 定期清理:添加定时任务,删除长时间未活跃的聊天流的消息
  3. 使用弱引用:考虑使用 weakref 来存储消息引用
  4. 设置过期时间:为每条消息添加 TTL(生存时间),定期清理过期消息

Notes

  • 这个问题在高活跃度的机器人实例中会更快地显现,特别是在 Debian 12 这样的长期运行的服务器环境中
  • 内存泄漏是渐进式的,所以可能需要运行一段时间后才会导致系统崩溃
  • 虽然代码中有数据库层面的记忆遗忘机制,但内存中的数据结构缺乏相应的清理逻辑
  • 建议开发者在 ChatManager 类中添加定期清理机制,或限制 last_messagesstreams 字典的大小

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)

如何重现此问题?

启动程序即会开始无限增长内存

可能造成问题的原因

last_messages 字典无限增长

系统环境

Debian12

Python 版本

Python 3.11

补充信息

No response

rfatfsg avatar Dec 01 '25 04:12 rfatfsg