我有一个C++程序,它调用很多trig函数.它已经运行了一年多了.我最近安装了gcc-4.8,并且同样去了,更新了glibc.这导致我的程序减慢了几乎x1000倍.使用gdb我发现减速的原因是调用std :: tan().当参数是pi或pi/2时,该函数需要很长时间才能返回.
这是一个MWE,如果没有优化编译就会重现问题(真实程序在有和没有-O2标志的情况下都有相同的问题).
#include <cmath>
int main() {
double pi = 3.141592653589793;
double approxPi = 3.14159;
double ret = 0.;
for(int i = 0; i < 100000; ++i) ret = std::tan(pi); //Very slow
for(int i = 0; i < 100000; ++i) ret = std::tan(approxPi); //Not slow
}
Run Code Online (Sandbox Code Playgroud)
这是来自gdb的示例回溯(使用Ctrl + c随机中断程序后获得).从调用tan开始,回溯在MWE和我的真实程序中是相同的.
#0 0x00007ffff7b1d048 in __mul (p=32, z=0x7fffffffc740, y=0x7fffffffcb30, x=0x7fffffffc890) at ../sysdeps/ieee754/dbl-64/mpa.c:458
#1 __mul (x=0x7fffffffc890, y=0x7fffffffcb30, z=0x7fffffffc740, p=32) at ../sysdeps/ieee754/dbl-64/mpa.c:443
#2 0x00007ffff7b1e348 in cc32 (p=32, y=0x7fffffffc4a0, x=0x7fffffffbf60) at ../sysdeps/ieee754/dbl-64/sincos32.c:111 …Run Code Online (Sandbox Code Playgroud) 函数在应用程序中花费的总时间可以大致分为两个部分:
通常,剖析器提供函数花费的总时间的估计.是否有可能估算出上述两个组件(Tcomp和Tmem)所花费的时间?
我正在开发嵌入式Linux(ARM)的应用程序.它将执行500次/秒,因此速度很重要.我更喜欢使用C++,但我担心它会比C慢,即使我避免像虚函数这样的奇特功能.是否有理由使用C或者用C++编写它就好了?
可能重复:
在终止进程之前保存gmon.out
我正在尝试在Linux环境中分析服务器(可用的源代码.c代码).该服务器像Web服务器一样连续运行.我正在尝试使用gprof来配置服务器.如果服务器自行退出,则会生成gmon.out文件.我可以使用gprof和gmon.out来理解配置文件数据.现在问题是,这台服务器正在连续运行,等待传入的套接字连接,请求等.如果我终止此服务器,则不会生成gmon.out.此时我看到以下选项.
编辑:服务器是多进程服务器.在FreeBSD 7.2上运行
我敢肯定,人们之前已经解决了这些问题.我没能在SO或外面找到有用的信息.
我感谢人们的任何想法/解决方案.
谢谢一堆.
更新1:
不知怎的,我设法为valgrind获得端口.当我运行make时,我得到以下错误.
=> valgrind-stable-352.tar.gz doesn't seem to exist in /usr/obj/ports/distfiles/.
=> Attempting to fetch from ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/distfiles/.
fetch: ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/distfiles/valgrind-stable-352.tar.gz: File unavailable (e.g., file not found, no access)
=> Attempting to fetch from http://www.rabson.org/.
fetch: http://www.rabson.org/valgrind-stable-352.tar.gz: No address record
=> Couldn't fetch it - please try to retrieve this
=> port manually into /usr/obj/ports/distfiles/ and try again.
*** Error code 1
Run Code Online (Sandbox Code Playgroud)
我试图在网上找到valgrind-stable-352.tar.gz.我找到的所有链接都已死亡.
我在我的freebsd上安装了pstack,实现的pstack只提供堆栈跟踪.参考:http://sourceforge.net/projects/bsd-pstack/
我的理解是systemtap仅用于内核空间事件,仪器等. …
我有兴趣分析Linux内核的模块.我这样试过:
CONFIG_PROFILING=yprofile=2echo 123 > /proc/profileioctl调用使用模块的用户空间应用程序.测试应用程序按预期工作,因此模块工作正常.readprofile -p /proc/profile -m System.map位置读取分析信息.到现在为止还挺好.几乎一切都按预期工作.什么也没有但是工作是,我没有得到我的模块任何信息,即没有从模块的任何功能的提及.
然而,在第二个想法,我记得我忘了重新编译模块使用CONFIG_PROFILING=y.
所以,我的问题是:模块是否没有出现在分析日志中,因为它没有编译过,CONFIG_PROFILING=y或者是否还有一些我不知道的更明显的原因?
如果有人想知道,为什么我要求而不是直接尝试,那是因为,我不能在家里做,而且我更愿意在再次访问代码之前听到知识渊博的话.
我已经读过很多开发人员使用x + = 1而不是x ++来清楚.我知道x ++对于新开发人员来说可能不明确,而且x + = 1总是更清晰,但两者之间的效率是否存在差异?
使用for循环的示例:
for(x = 0; x < 1000; x += 1) VS for(x = 0; x < 1000; x++)
我知道它通常不是那么大的交易,但如果我反复调用一个执行这种循环的函数,它可能会在长期内累加起来.
另一个例子:
while(x < 1000) {
someArray[x];
x += 1;
}
Run Code Online (Sandbox Code Playgroud)
VS
while(x < 1000) {
someArray[x++];
}
Run Code Online (Sandbox Code Playgroud)
可以用x + = 1代替x ++而不会造成任何性能损失吗? 我特别关注第二个例子,因为我使用两行而不是一行.
如何增加数组中的项?会someArray[i]++比someArray[i] += 1在大循环中完成时更快吗?
我已经尝试了所有可能的字段,但无法找到调用函数的次数.
此外,我没有得到Self和# Self.这两个数字是什么意思?
Brendan D. Gregg(DTrace书的作者)有一个有趣的分析变体:"Off-CPU"分析(和Off-CPU Flame Graph ; 幻灯片2013,p112-137),以查看线程或应用程序被阻止的位置(是不是由CPU执行,而是等待I/O,页面故障处理程序或由于CPU资源而导致的计划外停机:
这一次揭示了哪些代码路径在CPU外被阻塞和等待,以及准确的持续时间.这与传统的分析不同,后者通常以给定的间隔对线程的活动进行采样,并且(通常)只检查线程是否在CPU上执行工作.
他还可以将Off-CPU配置文件数据和On-CPU配置文件结合在一起:http://www.brendangregg.com/FlameGraphs/hotcoldflamegraphs.html
Gregg给出的示例是使用的dtrace,这在Linux OS中通常不可用.但是有一些类似的工具(ktap,systemtap,perf)和perf我认为最广泛的安装基础.通常perf生成On-CPU配置文件(这些功能在CPU上执行得更频繁).
perf成Linux中的分析工具?PS:来自LISA13,p124的幻灯片中有关于CPU外部火焰图的systemtap变体的链接:" Yichun Zhang创建了这些,并且已经在Linux上使用SystemTap来收集专业数据.请参阅:• http:// agentzh .org/misc/slides/off-cpu-flame-graphs.pdf " "(2013年8月23日的CloudFlare啤酒会议)
我在Java中有一个方法可以调用其他几种方法.从固定线程池中的多个线程调用此方法.工作线程数与可用处理器(核心数)相同.
public void query() {
method1();
method2();
}
Run Code Online (Sandbox Code Playgroud)
当我使用VisualVM分析程序执行时,时间method1()和method2()时间非常短,但query()自我时间很长.但除了两个调用之外,该方法没有其他代码.有可能是内部的同步method1()和method2(),但没有明显的代码,我管了.
当我将池中的工作者数量减少到1时,这个自我时间几乎消失了.整个程序的单线程和多线程执行时间几乎相同.我认为这意味着我的方法query()正在等待某事.
没有死锁,执行完成得很好.这两种方法method1(),并method2()调用了很多其他的事情,包括在混淆罐库中的类,所以它是不容易的,我调试.但是query(),使用该方法直接从工作线程调用java.util.concurrent.ExecutorService.
在 Java JVM 中,kill -3强制进程打印所有正在运行的线程的当前堆栈跟踪。我发现快速定位瓶颈非常有效。
V8 中是否有等价物?我可以让 V8 打印当前的堆栈跟踪吗?
澄清:我认为,由于节点的异步性质,它不如典型的非异步程序有用。尽管如此,如果有一种简单的方法可以访问一些堆栈跟踪,那么查看它并不需要太多时间。
根据我的经验,在您需要切换到更高级的工具之前,可以通过这种方式快速定位一些明显的瓶颈。
profiling ×6
c++ ×3
linux ×3
c ×2
perf ×2
performance ×2
arrays ×1
callgrind ×1
gcc ×1
glibc ×1
gprof ×1
increment ×1
instruments ×1
intel-vtune ×1
ios ×1
java ×1
linux-kernel ×1
macos ×1
node.js ×1
optimization ×1
profiler ×1
stack-trace ×1
v8 ×1
wait ×1
xcode ×1