-
我的一个高频接口性能差、GC 压力大,代码里却看不出哪行慢,profiler 一看全是堆分配,原来是我把一堆 int、bool 当 object 存进了集合、每次存取都在悄悄装箱拆箱的深度复盘
我有个高频调用的接口性能不理想、GC 频繁、内存分配率高,盯着代码看了半天每一行都很正常,实在找不出问题。直到用 profiler 抓内存分配才傻眼:大量堆分配集中在一段看起来人畜无害的代码上——我用了 Dictionary 存各种属性(里面塞了一堆 int、bool、DateTime 这些值类型)高频存取。复盘才搞懂:C# 里值类型默认在栈上或内联、不在堆上单独分配,但把它赋给 object(或…- 2
- 0
-
我在 C# 里打开了一堆文件流和数据库连接用完就不管了,以为有垃圾回收会自动清理,结果跑久了报 too many open files、连接池也满了,因为 GC 根本不负责释放这些非托管资源的深度复盘
我有段代码要读很多文件、查很多次数据库,写得很自然:new FileStream、new SqlConnection 用完就不管,心想 C# 有垃圾回收、对象没人引用了 GC 会自动清理。功能测试都过了,可一上压力、跑久了服务就崩:报 too many open files(文件句柄太多)、连接池满了、socket 也耗尽。复盘才搞懂:.NET 的 GC 只负责回收托管堆上的内存,但文件句柄、数据…- 0
- 0
-
我那些频繁创建又销毁的对象,订阅了一个单例的事件却忘了退订,结果它们一个都没被回收、内存一路涨到 OOM:一次 C# 事件订阅未取消导致内存泄漏的深度复盘
我有一类频繁创建又销毁的对象(随每个请求创建的 Handler),创建时订阅了一个长生命周期单例 EventBus 的事件:bus.DataChanged += this.OnDataChanged。功能没问题,可线上内存一路缓慢上涨、只涨不降,跑久了 OOM。内存 dump 才看明白:那些本该被回收的 Handler 一个都没被 GC,全被 EventBus 的委托链引用着。根因是它们订阅了单例…- 0
- 0
-
我的服务运行越久内存涨得越凶,最后内存泄漏到崩溃,排查发现是一堆本该被回收的对象因为订阅了事件却没取消订阅、被发布者死死攥着无法回收,我对着 C# 事件订阅导致的内存泄漏这个坑排查大半天的复盘
一个让我对有了 GC 就不会内存泄漏这个错觉彻底清醒的 C# 坑,隐蔽在 C# 有垃圾回收我一直以为对象没用了 GC 自然会回收根本不用操心,可这次一堆本该被回收的对象却被一根我没注意到的引用线死死拴住、GC 怎么也回收不了。服务运行越久内存涨得越凶最后 OOM 崩溃。场景:短生命周期对象 TempHandler 订阅了长生命周期全局服务 GlobalService 的 DataChanged 事…- 2
- 0
-
页面明明都关了,程序内存却只升不降、最后被撑爆:我在 C# 里订阅了事件却忘了退订,埋下的那个悄无声息的内存泄漏的深度复盘
客户端程序的页面反复开关,内存却只升不降、最后撑爆。内存分析发现:那些"已关闭"的页面对象一个都没被 GC 回收!根因是页面在打开时订阅了长寿的"数据中心"单例的事件、关闭时却忘了退订——而订阅事件会让发布者持有对订阅者的引用,长寿的数据中心就一直拴着本该销毁的页面,导致它永远无法回收。这篇从事件订阅为何泄漏(发布者引用+GC规则+谁更长寿)讲到 -= 退订…- 0
- 0
-
服务跑一段时间就报连接池已满和打开文件太多、重启又复发像慢慢漏气的轮胎:IDisposable 资源没 Dispose 导致连接句柄泄漏的避坑复盘
这是一个跑着跑着就枯竭的慢性病,和我之前遇到的内存泄漏有几分神似但病根不同。现象是我们一个 C# 写的服务刚启动时一切正常,可运行一段时间后几小时到一两天不等就开始报错,一会儿是数据库相关的连接池已满无法从池中获取连接,一会儿又是 Too many open files 打开的文件句柄太多,重启一下好了再跑一段时间又复发,就像一个会慢慢漏气的轮胎跑一阵就瘪补一下又能跑一阵。排查的结果指向了 C# …- 0
- 0
-
事件订阅没退订:C# 内存缓慢泄漏避坑复盘
有个长期运行的 C# 服务跑着跑着内存就缓慢不可逆地往上涨,几天就逼近上限不得不重启,不像一下子爆掉而是温水煮青蛙式一点一点涨极难察觉,直到监控曲线连成一条只升不降的斜线。抓内存快照分析发现堆里积压了海量本该回收的对象——一类视图模型对象明明业务早结束、外部也不再引用,却像幽灵赖在内存里死活不被 GC 回收。顺引用链往上追真凶浮出水面:它们都被一个事件牵住了。原来这些短命视图模型创建时订阅了某个长…- 0
- 0
-
GC 语言也会内存泄漏:Python 服务被 OOM 反复杀死的排查
一个稳稳跑了好几个月的数据处理服务,突然开始被 OOM Killer 反复杀死:重启,过几小时,又被干掉。盯着监控曲线看,那条内存线像爬楼梯一样只涨不跌,撞到上限被杀、清零、再爬。这是教科书级的内存泄漏症状——可这是 Python,一门带垃圾回收的语言,怎么还会漏?几天排查下来真相平淡得让人脸热:漏的不是解释器,正是我们自己的代码。一个图省事的可变默认参数、一个只进不出的全局缓存字典、再加几处循环…- 2
- 0
-
从粗放 JVM 运维 CMS 大促高峰 Full GC 十几秒 STW 把交易服务冻死大面积超时 + 默认参数裸跑从不按负载调堆和分代 + 静态 Map 缓存无上限只进不出缓慢漏到 OOM 周期性崩溃重启 + 性能问题靠几个人围一起凭印象猜哪段慢挑可疑处改改上线试盲人摸象白忙几天 + 热点路径循环里反复 new 加字符串 + 拼接加装箱海量临时对象涌入新生代 Young GC 频繁晋升加重 Full GC + 线程池核心数最大数队列长全靠拍脑袋甚至用 Executors 无界队列任务积压到 OOM + 共享数据无脑 synchronized 锁整个方法粒度极粗高并发大批线程挤一把锁排队吞吐被锁死 + 堆外 DirectByteBuffer 泄漏堆内监控一切正常进程却被容器 OOM Killer 反复杀查大半天没头绪 + 不懂 JIT 新实例冷启动全解释执行刚接流量就大量超时误判成网络问题 + 线上 JVM 黑盒平时不看出事才 SSH 上去 jmap 导几十G大堆把垂危服务彻底压垮 → 2026 现代 JVM 性能工程 G1/ZGC 低延迟回收设停顿目标 + 按负载调堆 Xms=Xmx 分代 + HeapDumpOnOutOfMemoryError 加 MAT 引用链定位泄漏加 Caffeine 缓存上限 + JFR 加 async-profiler 火焰图数据驱动定位热点 + StringBuilder 加预分配容量加避免装箱加逃逸分析减分配 + ThreadPoolExecutor 精细化有界队列加拒绝策略加命名 + ConcurrentHashMap 加 LongAdder 替代重锁 + NMT 原生内存追踪加 MaxDirectMemorySize 治堆外 + 分层编译加预热 warm-up 解决冷启动 + JFR 持续黑匣子加 Micrometer 加 Prometheus/Grafana 可观测 87 天战役复盘:47 套工程修法 + 7 个 P0 复盘 + 6 条工程哲学
9 人的 Java 平台与性能工程团队 87 天把一套跑了六年、日交易量从每天几百万笔涨到几亿笔后 JVM 性能问题集中爆雷的核心交易系统——大促高峰期老问题 CMS 因老年代碎片触发 Full GC 一停就是十几秒 STW 把整个交易服务冻死导致大面积超时、JVM 参数基本是默认裸跑从来没有按照服务的负载特征去认真调过堆大小和分代比例、一个静态 Map 当缓存用却没设任何上限只进不出运行十几天就…- 2
- 0
-
Go sync.Pool 在小对象高频场景反而拖慢 P99 + GC 抖动放大的 5 天复盘:victim cache + GC 周期耦合 + Batch Pool 正解
18 万 QPS 推送网关给 256 字节 PushContext 加了 sync.Pool,benchmark 漂亮但生产 P99 从 8ms 飙到 23ms,GC 频率反而涨到 2.34/秒。5 天复盘揭开 victim cache + GC 周期耦合的反直觉负优化机制,最终落地按对象大小/寿命决定是否池化的判断准则 + Batch Pool 正解。- 0
- 0
-
Go 推荐服务 P99 480ms 每几小时抖动一次的 4 天复盘:容器化下被动 forced GC 三因素叠加 + GOMEMLIMIT/GOGC 双保险落地
2026 年 3 月,Go 推荐服务 reco-service 每隔 3-6 小时 P99 飙到 480ms,持续 10-30 秒后自动恢复,4 个月查不到根因。这次带 GODEBUG=gctrace=1 抓现场,定位是 Go GC 在大堆 + K8s memory limit 3GB + 默认 GOGC=100 三因素叠加引发的被动 forced GC,Mark phase 抢 25% CPU …- 2
- 0
-
Go GC STW 在 180GB 堆下飙到 800ms 导致风控漏判的复盘:5 种修法从指针消灭到 mmap
一次例行数据更新让 Go 风控引擎的堆从 120GB 涨到 180GB,GC Mark Termination STW 从 1ms 飙到 800ms,刚好命中上游 500ms 超时,触发 4 小时漏判 230 笔潜在欺诈交易、估损 80 万。这篇完整复盘事故时间线、Go 三色标记 GC 真正的 STW 暴涨原因、GOGC/GOMEMLIMIT/消灭指针/mmap off-heap/服务拆分五种修法…- 3
- 0
-
JVM 内存与 GC 完全指南:从一次半夜 OOM 告警看懂堆内存怎么排查
2023 年的一个凌晨两点,我被告警电话叫醒:一个核心 Java 服务被系统 OOM Killer 杀掉了。重启、又挂、再重启,堆内存像一条笔直的斜线一路往上爬,涨到顶就崩。我第一反应是"流量涨了内存不够",准备提工单扩容——幸好在提单之前先把堆 dump 下来看了一眼:堆里 80% 的空间被一个 static HashMap 占着,塞了几百万个对象,一个都没被清理。这根本不是…- 7
- 0
-
JVM G1 切 ZGC 两周调参实录:p99 GC 暂停 80ms→3ms
JVM Full GC 每分钟一次,p99 飙 800ms。G1 调参 + 切 ZGC 全实录:JVM GC 算法对比 + G1 关键参数 + ZGC 染色指针 + 内存增加权衡 + NMT 排查 + JFR + 监控告警 + 不同场景 GC 选型。p99 暂停 80ms→3ms。- 3
- 0
-
G1 换 ZGC 实战:p99 从 480ms 降到 95ms,踩了 4 个坑
延迟敏感网关把 G1 换 ZGC,p99 从 480ms 降到 95ms。但中间踩坑:堆外内存暴涨被 OOMKilled、CPU +30%、监控数据失真、Allocation Stall。本文写实记录 4 个坑 + JFR 调试 + JDK 21 分代式 ZGC 数据 + 选型建议,附完整启动参数。- 0
- 0
-
垃圾回收机制详解:从引用计数到三色标记的完全指南
"我的程序内存为什么涨了?""GC 为什么停顿这么久?"几乎每个写过 Java / Go / Node / Python 的人都问过。要回答这些问题,必须理解垃圾回收(GC)的几种基本算法和现代语言的实现选择。这篇文章用一致的视角讲完所有主流 GC,让你看到任何一篇 GC 调优文档都能知道它在说什么。 垃圾的定义 "垃圾"就是"…- 0
- 0
GC
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!
















