Twenty 内存越跑越高?用 DevTools 快照对比三步锁定泄漏源头
2026/8/30 8:21:52 网站建设 项目流程

Twenty 内存越跑越高?用 DevTools 快照对比三步锁定泄漏源头

【免费下载链接】twentyThe open alternative to Salesforce, designed for AI.项目地址: https://gitcode.com/GitHub_Trending/tw/twenty

Twenty 的 CRM 页面开着开着就卡,任务管理器里它的内存条蹭蹭往上涨,关掉弹层也不回落。这篇文章带你用 Chrome DevTools 的 Memory 面板做 Twenty 内存泄漏排查:录一次分配、对比两次快照,把泄漏源头锁定到具体模块。

先搞清 Twenty 的内存卡在哪

内存泄漏说白了就是:对象没人用了,引用却还在,GC 收不走。Twenty 是重前端架构,packages/twenty-front/src/modules/ 下五十来个模块(Jotai 状态、SSE 订阅、命令菜单)常驻内存;AI 与工作流模块又会在长任务里持续产生对象。所以前端用 DevTools 查,服务端缓存侧靠监控确认,这里只讲浏览器里的那一半。

动手前:30秒把工具备齐

  • 拉取 Twenty 源码:git clone https://gitcode.com/GitHub_Trending/tw/twenty
  • 按项目文档把 Twenty 跑起来,浏览器里能正常登录并打开 CRM 页面
  • 页面按F12(或Ctrl+Shift+I)打开 Chrome DevTools,切到Memory面板
  • 确认页面处于日常真实使用状态:有视图、有工作流记录、AI 功能可用

上图:排查前确认 Twenty 应用正常运行、功能可触达(设置页 Webhook 测试界面)

实操:从按下录制键到锁定嫌疑对象

用 Allocation Sampling 抓一轮分配

  1. Memory 面板顶部分类下拉里选Allocation sampling,点Record
  2. 去 Twenty 里走一遍日常动线:切对象视图、筛选数据、触发一次 AI 功能,约 1-2 分钟,回来点Stop

看采样表里Bytes最高的几条调用栈。如果大头集中在业务模块的某个函数上,泄漏嫌疑基本就在它那一片;如果大头是框架内部(如 React Fiber),说明是业务代码持有了框架对象不放,继续往下查。

按 Retained Size 排序揪出大头

  1. 分类改选Heap snapshot,点Take heap snapshot,作为基线(此刻页面刚打开、尽量干净)
  2. 再做一轮操作,回到 Memory 面板,点Garbage collect按钮触发一次 GC,再拍第二张快照
  3. 在对象列表的Retained Size列上点一下排序,从大到小看

Retained 值大且带closure/Fiber/ 定时器回调特征的节点,就是你的一号嫌疑人。注意:单看绝对值意义不大,一张快照只能说明"现在大",不能说明"在涨"。

对比两次快照确认只涨不跌

  1. 打开第二张快照,上方显示模式下选Comparison,对比对象选第一张基线
  2. 只看Delta为正的对象,按 Delta 排序

如果某类对象(闭包、Fiber、SSE 回调、定时回调)在两轮操作间只增不减,大概率就是泄漏;如果 Delta 基本持平,那只是正常缓存,不用慌。

上图:Twenty 应用内界面示例——这类视图页面就是内存快照对比时的操作对象

排查清单:4种最高频的泄漏源头

泄漏类型你看到的现象去哪找(项目内模块)怎么修
隐式全局变量快照里window子树挂着业务对象packages/twenty-front/src/modules/browser-event赋值前补上const/let声明
定时器残留快照反复出现setTimeout/setInterval回调packages/twenty-front/src/modules/ai、packages/twenty-front/src/modules/sse-db-event清理函数里clearInterval
事件监听未成对移除#listeners里同名 handler 越积越多packages/twenty-front/src/modules/keyboard-shortcut-menu、packages/twenty-front/src/modules/side-paneladdEventListenerremoveEventListener配对
缓存只进不出服务端内存缓涨、对象量平稳上升packages/twenty-server/src/engine/core-entity-cache、packages/twenty-server/src/engine/workspace-cache给缓存补 TTL 或容量上限
// 错误:忘声明的赋值挂到 window 上 function tick() { pending = fetchNext(); } // 正确:const pending + 卸载时 clearInterval(timer)

让内存占用长期不超标

  • 给前端缓存和实体缓存设过期时间或容量上限,别让 map 无限长大
  • 组件卸载时把定时器和事件监听一起摘掉,和挂载逻辑写在同一处
  • AI 长任务的结果用完就解绑,别挂在页面级长生命周期对象上
  • 关键模块改动后重跑一遍本文的快照对比,Delta 为正就停手修掉 ⚡
  • SSE 订阅随视图生命周期创建和销毁,切走视图时确认订阅被取消

一轮"采样→快照→对比"十几分钟就能跑完,胜在便宜、可复现,比对着日志猜强得多。明天打开 Twenty,把这篇的三步走一遍——如果 Delta 里揪出了闭包,直接顺着它去 packages/twenty-front/src/modules/ 里查谁没放手。

【免费下载链接】twentyThe open alternative to Salesforce, designed for AI.项目地址: https://gitcode.com/GitHub_Trending/tw/twenty

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询