使用valgrind检查内存问题并且输出报告

valgrind内存泄漏分析

是在linux中检查内存泄漏的工具。当程序编写完之后我一般都会使用它来检查一次内存问题。基本上能杜绝服务器的内存泄漏问题(当然是面对C/C++这样的语言的)。
使用方式就是将程序编译好,然后通过valgrind来启动程序。当测试完全部的内存测试用例之后,让服务器程序正常退出。在最后结束的时候将会输出服务器的内存泄漏报告。不过valgrind对于protobuf,stl这样的3方库的兼容性不算太好,所以会造成输出一堆的still reachable字样。其实完全没有必要去纠结这些问题。可以肯定这些都是误判的。当你使用了这样的库的情况下,一般都会需要将这些检查option关闭掉。防止自己被爆出来的一堆的错误唬住了。信息太多反而阻碍自己的判断。
下面是一般启动程序使用的指令:

valgrind --log-file=./valgrind_report.log --track-origins=yes --leak-check=full --show-leak-kinds=all --show-reachable=no ./

这个里面使用到的option分别的意义:

–log-file
指定报告输出文件
–track-origins=yes
是否显示未定义的变量,在堆、栈中被定义没有被initialised的变量都被定义成origins。默认是关闭这个option的。
–show-leak-kinds=all
这里可以支持的选项有[definite|possible],一般只需要去关注definite(绝逼),possible是可能会存在。
–leak-check=full
当服务器退出时是否收集输出内存泄漏,选项有[no|summary|full]这个地方我们将其设置成全输出,默认将会使用summary方式。

输出报告之后重点看definite的,而且关于自己程序的。其次再去看possible的内存分配点的释放。

收集linux进程内存数据

对于在linux中的进程内存使用在/proc/[pid]/statm文件中其实是写了进程的内存使用情况。如果我们想去分析一个进程的内存长时间使用的趋势,可以在crontab中写一个定时运行的脚本通过读取这个文件来定时采集服务器的内存使用情况。如果服务器中安装了mysql数据库,可以使用命令行将这些数据入库。然后通过chart.js+php将数据通过图表方式呈现出来。数据收集了之后,其实也是没法子判断出数据的趋势。所以得让数据图形化。

/proc/[pid]/status文件中我们可以抓取服务器的内存相关的信息(单位为bytes):

VmPeak:   393532 kB
VmSize:   393532 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     35012 kB
VmRSS:     35012 kB
VmData:   328460 kB
VmStk:       268 kB
VmExe:      2248 kB
VmLib:     12836 kB
VmPTE:       228 kB
VmSwap:        0 kB

VmPeak = 虚存历史最高值
VmSize = 虚存
VmHWM = 物理内存最高值
VmRSS = 物理内存
VmData, VmStk, VmExe = 数据、栈和文本代码内存
VmLib = 共享库代码内存大小
VmPTE = 全部页表内存大小
VmLck = 锁定内存大小(参考:mlock)
VmSwap = 交换

/proc/[pid]/statm文件中对于内存的描述如下(度量单位是页):
提供某个pid下的内存使用情况。下面是每页的含义:

列编号 名称 详解
1 size 全部程序的大小,就是top中的VIRT虚存大小
2 resident 程序使用的实存,在top中的Res
3 share 共享页大小
4 text 文本(代码)
5 lib 库(Linux2.6无用)
6 data 数据和堆
7 dt 脏页大小(Linux 2.6无用)

为了直观理解的方便,我们可以使用bytes方式。
接下来就是将入库之后的内存做出曲线图了。这里需要使用的技术是apache+php+chart.js。
我们只需要编写一个页面来实现这个功能。在web世界里面,php是跑在服务器段的,它负责去在服务器中执行并且获得返回信息。并且通过打印字符串通过apache将这些http的文本发给browse。当browse拿到http文本,如果读取到了js这种前段的脚本,就会根据文本在本地绘画。我们这个示例就是通过php去读取mysql中我们已经收集到的某个服务器的memory的历史使用趋势数据。并且将数据写入到http中,并且填充一个js脚本。

连接MySQL读取数据


<?
 $mysql_server_name="127.0.0.1"; //数据库服务器名称
    $mysql_username="xxx"; // 连接数据库用户名
    $mysql_password="xxx"; // 连接数据库密码
    $mysql_database="xxx"; // 数据库的名字

    // 连接到数据库
    $conn=mysql_connect($mysql_server_name, $mysql_username,
                        $mysql_password);

     // 从表中提取信息的sql语句
    $strsql="SELECT * FROM `MEM_LOG`";
    // 执行sql查询
    $result=mysql_db_query($mysql_database, $strsql, $conn);
    // 获取查询结果
    $row=mysql_fetch_row($result);



    $labels = array();
    $vm = array();
    $rm = array();
    $lua = array();

    mysql_data_seek($result, 0);
    // 循环取出记录
    while ($row=mysql_fetch_row($result))
    {
        array_push($labels, $row[0]);
        array_push($vm, $row[1]);
        array_push($rm, $row[2]);
        array_push($lua, $row[3]);
    }

    // 释放资源
    mysql_free_result($result);
    // 关闭连接
    mysql_close($conn);  

创建js的画布

注意:这里是下载了一份Chart.js-1.0.2放到了站点的根目录。否则会报错说这个js找不到。

<script src="Chart.js-1.0.2/Chart.js">
</script> <canvas id="myChart" width="1800" height="400"></canvas>

通过php来填充一个js脚本文本

这个具体的实例,可以去抄一下chart.js的官方的一些实例就能去做饼状图,具状图之类的了。

    echo json_encode($labels);
    echo '<br/>';
    echo ' <script type="text/javascript"> var data = { labels: ' . " " .  json_encode($labels) . " " .  ', datasets: [ { label: "Vm", fillColor: "rgba(220,220,220,0.2)", strokeColor: "rgba(220,220,220,1)", pointColor: "rgba(220,220,220,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(220,220,220,1)", data: ' . " " .  json_encode($vm) . " " .  ' }, { label: "rm", fillColor: "rgba(151,187,205,0.2)", strokeColor: "rgba(151,187,205,1)", pointColor: "rgba(151,187,205,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(151,187,205,1)", data: ' . " " .  json_encode($rm) . " " . ' }, { label: "lua", fillColor: "rgba(120,120,120,0.2)", strokeColor: "rgba(120,120,120,1)", pointColor: "rgba(120,120,120,1)", pointStrokeColor: "#fff", pointHighlightFill: "#fff", pointHighlightStroke: "rgba(220,220,220,1)", data: ' . " " .  json_encode($lua) . " " .  ' } ] }; </script>';

conclusion

最后如果你想将一个服务器的内存吃准了,其实还是来自于平日里对于服务器的把控。如同编制竹篓子,平时下功夫檫亮眼睛去多检查就扎实了。即使崩了也不会一泻千里的坏掉。

你可能感兴趣的:(PHP,内存,C语言,valgrind,chart-js)