
看懂程序的性能
对客户端程序而言 拙劣的性能会严重影响用户体验 界面停顿 抖动 响应迟钝等问题会遭到用户不停的抱怨 一个典型的例子就是Eclipse IDE工具在Full GC时会出现程序假死现象 相信一定被不少开发人员所诟病 对于服务器程序来说 性能问题则更为重要 相信不少后台服务器软件都有各自的性能目标 以Web服务器为例 服务器的响应时间 吞吐量就是两个重要的性能参数 当服务器承受巨大的访问压力时 可能出现响应时间变长 吞吐量下降 甚至是抛出内存溢出异常而崩溃 这些问题 都是性能调优需要解决的
一般来说 程序的性能通过以下几个方面来表现
执行速度 程序的反映是否迅速 响应时间是否足够短
内存分配 内存分配是否合理 是否过多地消耗内存或者存在泄漏
启动时间 程序从运行到可以正常处理业务需要花费多长时间
负载承受能力 当系统压力上升时 系统的执行速度 响应时间的上升曲线是否平缓
返回目录 Java程序性能优化 让你的Java程序更快 更稳定
编辑推荐
Visual C++音频/视频技术开发与实战
Oracle索引技术
lishixinzhi/Article/program/Java/gj/201311/27850address sanitizer(简称asan)是一个用来检测c/c++程序的快速内存检测工具。相比valgrind的优点就是速度快,官方文档介绍对程序性能的降低2倍。
对Asan原理有兴趣的同学可以参考asan的算法这篇文章,它的实现原理就是在程序代码中插入一些自定义代码,如下:
编译前:
*address = ...// or: ... = *address
编译后:
if (IsPoisoned(address)) {undefined
ReportError(address, kAccessSize, kIsWrite)
}
*address = ...// or: ... = *address`
和valgrind明显不同的是,asan需要添加编译开关重新编译程序,好在不需要自己修改代码。而valgrind不需要编程程序就能直接运行。
address sanitizer集成在了clang编译器中,GCC 4.8版本以上才支持。我们线上程序默认都是使用gcc4.3编译,于是我测试时直接使用clang重新编译nginx:
--with-cc="clang" \
--with-cc-opt="-g -fPIC -fsanitize=address -fno-omit-frame-pointer"
其中with-cc是指定编译器,with-cc-opt指定编译选项, -fsanitize=address就是开启AddressSanitizer功能。
由于AddressSanitizer对nginx的影响较小,所以大压力测试时也能达到上万的并发,内存泄漏的问题很容易就定位了。
这里就不详细介绍内存泄漏的原因了,因为跟openssl的错误处理逻辑有关,是我自己实现的,没有普遍的参考意义。
最重要的是,知道valgrind和asan的使用场景和方法,遇到内存方面的问题能够快速修复。
性能热点分析
到此,经过改造的nginx程序没有core dump和内存泄漏方面的风险了。但这显然不是我们最关心的结果(因为代码本该如此),我们最关心的问题是:
1. 代码优化前,程序的瓶颈在哪里?能够优化到什么程度?
2. 代码优化后,优化是否彻底?会出现哪些新的性能热点和瓶颈?
这个时候我们就需要一些工具来检测程序的性能热点。
perf,oprofile,gprof,systemtap
1)尽量指定类、方法的final修饰符。带有final修饰符的类是不可派生的,Java编译器会寻找机会内联所有的final方法,内联对于提升Java运行效率作用重大,此举能够使性能平均提高50%。
2)尽量重用对象。由于Java虚拟机不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理,因此生成过多的对象将会给程序的性能带来很大的影响。
3)尽可能使用局部变量。调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快,其他变量,如静态变量、实例变量等,都在堆中创建速度较慢。
4)慎用异常。异常对性能不利,只要有异常被抛出,Java虚拟机就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。异常只能用于错误处理,不应该用来控制程序流程。
5)乘法和除法使用移位 *** 作。用移位 *** 作可以极大地提高性能,因为在计算机底层,对位的 *** 作是最方便、最快的,但是移位 *** 作虽然快,可能会使代码不太好理解,因此最好加上相应的注释。
6)尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用 Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销。
尽量在合适的场合使用单例。使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)