文章归档

memory allocator and coredump analysis

这几天彻底被一个线上BUG搞跨了,我们准备上线一个新的模块,灰度的时候发现系统极其不稳定,几乎每过几十分钟就core一次,而且coredump的地方比较有规律。现在来回顾一下这个core的分析过程

coredump现象

我们上线的流程是 稳定性测试 + 小流量灰度 + 全量上线 稳定性测试的机器环境是centos 6,线上自己的环境是 centos 5.4,稳定性测试的时候从线上拷贝流量,启动所有模块,持续跑了两天没有发现问题,然后接着小流量灰度。(后来的事实说明,环境也是导致coredump触发的一个很重要因素)

小流量灰度的时候问题出现了,时不时的core一下,core的地方比较稳定,每次都差不多都是那几个地方。既然core的比较稳定,说明应该是附近的代码出现了问题。

信息收集

从coredump的栈帧信息来看,现在能确定的是:

  • core在stl内部,说明不是明显的NULL引用等引发的coredump
  • 用户态极少使用malloc/free等来分配释放内存
  • coredump比较稳定,附近代码有问题的可能性比较大

静态代码分析

由于初步分析coredump处附近

  • 分析coredump代码附近有可疑的地方,例如数组越界,多线程race condition,不正确的malloc/free等等,没有发现问题。
  • 分析新上线的代码,例如有可能引入或者触发coredump的地方,没有发现问题。
  • 检查线程安全,race condition的地方,例如多线程读写map等

排查

初步分析没有发现明显的问题后,我们开始一步一步的排查和定位问题。通过配置线上可运行的模块,定位到其中某个模块可能有问题。由于静态代码分析的 时候看过这部分代码,很难定位到出问题的地方。加上在排查过程中即使卸载可疑的模块,仍然没法彻底解决问题,只是降低了coredump之间的时间间隔

coredump很可能不是在crash的地方附近,而是在之前别的地方就已经被破坏掉了。

Valgrind

为了证实这个问题,我们对所有模块都做了一次长时间的Valgrind测试,最终发现一个已经长时间运行的模块存在一个BUG,这个BUG非常难捕捉到,主要是由于一个Json的不正确使用导致的,走了一条很少有的执行路径,触发了此BUG

这个问题为什么之前没有爆发出来呢?double free这种错误会由于内存管理器的实现不用而表现出不稳定性,原因是假设你轻微地破坏了一块内存,而且被破坏的地方不影响别的内存块,那么如果这块内存 释放后并没有被重复利用,这个BUG就难以复现出来。所以我们看到coredump的地方未必是问题发现的地方。

Profiling Go Program

- http://blog.golang.org/2011/06/profiling-go-programs.html

At Scala Days 2011 a few weeks ago, Robert Hundt presented a paper titled “Loop Recognition in C++/Java/Go/Scala.” The paper implemented a specific loop finding algorithm, such as you might use in a flow analysis pass of a compiler, in C++, Go, Java, Scala, and then used those programs to draw conclusions about typical performance concerns in these languages. The Go program presented in that paper runs quite slowly, making it an excellent opportunity to demonstrate how to use Go's profiling tools to take a slow program and make it faster.

By using Go's profiling

»» 继续阅读全文

Linux Performance Analysis and Tools

原文:Linux performance analysis and tools