IT

스택 샘플링을 넘어서 : C ++ 프로파일 러

lottoking 2020. 6. 18. 07:33
반응형

스택 샘플링을 넘어서 : C ++ 프로파일 러


해커의 이야기

날짜는 12/02/10입니다. 크리스마스 전날이 흘렀고 저는 Windows 프로그래머로서 주요 도로 블록에 거의 부딪 쳤습니다. 나는 AQTime을 사용하고 있고, 졸리고, 반짝 거리며, 매우 졸려 보았고, VTune이 설치되고 있습니다. VS2008 프로파일 러를 사용하려고 시도했으며 긍정적으로 처벌을 받았으며 종종 무의미했습니다. 무작위 일시 중지 기술을 사용했습니다. 콜 트리를 검사했습니다. 함수 추적을 해고했습니다. 그러나 문제의 슬픈 고통스러운 사실은 내가 작업하는 앱이 백만 줄 이상의 코드이며 아마도 다른 백만 줄의 타사 앱이 있다는 것입니다.

더 나은 도구가 필요합니다. 다른 주제를 읽었습니다. 각 주제에 나열된 각 프로파일 러를 사용해 보았습니다. 이 엉뚱하고 값 비싼 옵션보다 더 나은 것이 있거나, 거의 이득이없는 음란 한 양의 작업이 있어야합니다. 문제를 더 복잡하게하기 위해, 우리 코드는 스레드가 많고, 많은 Qt 이벤트 루프를 실행하는데, 그 중 일부는 너무 약해서 타이밍 지연으로 인해 무거운 계측에서 충돌합니다. 왜 우리가 여러 이벤트 루프를 실행하는지 묻지 마십시오. 아무도 나에게 말할 수 없습니다.

Windows 환경에서 Valgrind 라인을 따라 추가 옵션이 있습니까?
이미 시도한 긴 도구들보다 더 좋은 것이 있습니까?
큐에 이벤트를 유용하게 표시하여 Qt와 통합하도록 설계된 것이 있습니까?

기울임 꼴에 실제로 유용한 도구와 함께 시도한 도구의 전체 목록 :

  • AQTime : 오히려 좋습니다! 깊은 재귀에 문제가 있지만 이러한 경우 호출 그래프가 정확하며 혼란을 제거하는 데 사용할 수 있습니다. 완벽한 도구는 아니지만 시험해 볼 가치가 있습니다. 그것은 당신의 필요에 맞을 수도 있으며, 대부분의 경우 나에게 충분했습니다.
  • 디버그 모드에서 임의 일시 정지 공격 : 충분한 정보가 충분하지 않습니다.
    좋은 도구이지만 완벽한 솔루션은 아닙니다.
  • 병렬 스튜디오 : 핵 옵션. 눈에 거슬 리고 이상하고 미치도록 강력합니다. 나는 당신이 30 일 평가를 치고 그것이 잘 맞는지 알아 내야한다고 생각합니다. 너무 멋지다.
  • AMD Codeanalyst : 훌륭하고 사용하기 쉽고 충돌이 발생하기 쉽지만 환경 문제라고 생각합니다. 무료이므로 시도해 보는 것이 좋습니다.
  • Luke Stackwalker : 소규모 프로젝트에서 잘 작동합니다. 우리 프로젝트에서 약간의 노력을 기울이고 있습니다. 그래도 좋은 결과가 있으며, 개인적 작업으로 슬리피를 대체합니다.
  • PurifyPlus : Win-x64 환경, 가장 두드러진 Windows 7은 지원되지 않습니다. 다른 부서의 많은 동료들이 맹세합니다.
  • VS2008 프로파일 러 : 필요한 분해능에서 기능 추적 모드에서 100+ 기가 범위의 출력을 생성합니다. 긍정적 인면에서 확실한 결과를 만들어냅니다.
  • GProf : GCC가 어느 정도 효과적이어야합니다.
  • VTune : VTune의 W7은 범죄에 대한 국경을 지원합니다. 그렇지 않으면 우수
  • PIN : 내 도구를 해킹해야하므로 최후의 수단입니다.
  • Sleepy \ VerySleepy : 작은 앱에는 유용하지만 여기서 실패합니다.
  • EasyProfiler : 계측 할 위치를 표시하기 위해 수동으로 삽입 된 코드가 마음에 들지 않으면 나쁘지 않습니다.
  • Valgrind : * nix 만 해당 환경에있을 때 매우 좋습니다.
  • OProfile : Linux 전용.
  • Proffy : 그들은 야생마를 쏴요.

내가 시도하지 않은 제안 도구 :

  • XPerf :
  • 글로우 코드 :
  • 개발자 :

참고 : 현재 인텔 환경. VS2008, 부스트 라이브러리. Qt 4+. 트롤 테크를 통한 Qt / MFC 통합.


이제 : 거의 2 주 후에 문제가 해결 된 것 같습니다. 목록에있는 거의 모든 것을 포함하여 몇 가지 개인 트릭을 포함한 다양한 도구 덕분에 우리는 주요 병목 현상을 발견했습니다. 그러나 저는 새로운 테크놀러지뿐만 아니라 새로운 프로파일 러를 계속 테스트하고 탐구하고 시도 할 것입니다. 왜? 내가 너희들에게 빚을 졌기 때문에 너희들은 흔들 리기 때문이다. 타임 라인이 약간 느려지지만 새로운 도구를 계속 사용해 봐서 매우 기쁩니다.

개요
많은 다른 문제 중에서, 최근에 많은 구성 요소가 잘못된 스레딩 모델로 전환되어 우리 밑의 코드가 갑자기 더 이상 멀티 스레딩되지 않았기 때문에 심각한 중단을 일으켰습니다. NDA를 위반하기 때문에 더 이상 말할 수는 없지만 이것이 일상적인 검사 또는 정상적인 코드 검토로는 발견되지 않았 음을 알 수 있습니다. 프로파일 러, 콜 그래프 및 임의의 일시 정지가 없으면 하늘의 아름다운 푸른 호에서 우리의 분노가 계속 비명을 질 것입니다. 고맙게도, 내가 만난 최고의 해커들과 함께 일하며, 훌륭한 도구와 훌륭한 사람들로 가득한 놀라운 '구절에 접근 할 수 있습니다.

젠틀 포크, 나는 이것을 대단히 감사하며, 당신에게 현상금으로 보상 할 충분한 담당자가 없다는 것을 유감스럽게 생각합니다. 나는 아직도 이것이 지금까지 우리가 얻은 것보다 더 나은 답변을 얻는 데 중요한 질문이라고 생각합니다.

결과적으로, 매주 다음 3 주 동안, 나는 내가 감당할 수있는 가장 큰 현상금을 내고, 그것이 상식이 아니라고 생각하는 가장 멋진 도구로 대답 할 것입니다. 3 주 후, 우리가 내 삐걱 거리는 소리를 용서한다면 프로파일 러에 대한 명확한 프로파일을 축적했으면합니다.

테이크 아웃
프로파일 러를 사용하십시오. Ritchie, Kernighan, Bentley 및 Knuth에 충분합니다. 당신이 누구라고 생각하든 상관 없습니다. 프로파일 러를 사용하십시오. 가지고있는 것이 작동하지 않으면 다른 것을 찾으십시오. 찾을 수 없으면 코드를 작성하십시오. 코드를 작성할 수 없거나 약간 끊어 지거나 막힌 경우 임의 일시 중지를 사용하십시오. 다른 모든 방법이 실패하면, 일부 졸업생을 고용하여 프로파일 러를 강타하십시오.


더 긴 전망
그래서 약간의 회고를 작성하는 것이 좋을 것이라고 생각했습니다. 실제로 PIN 도구 위에 구축되어 있기 때문에 Parallel Studios에서 광범위하게 작업하기로 결정했습니다. 관련된 일부 연구자들과 학문을 다루면서 나는 이것이 아마도 어느 정도의 질이라고 생각했다. 고맙게도 나는 옳았다. GUI가 약간 두려운 반면, IPS는 매우 유용하지만 모든 사람에게 편안하게 추천 할 수는 없습니다. 비판적으로, 라인 레벨 적중 횟수, AQT 및 기타 여러 프로파일 러가 제공하는 확실한 방법은 없으며 다른 것들 중에서 분기 선택 속도를 검사하는 데 매우 유용합니다. 순전히, 나는 AQTime을 사용하는 것을 즐겼으며, 그들의 지원이 실제로 반응하는 것을 발견했습니다. 다시 한 번, 추천을 받아야합니다. 많은 기능들이 제대로 작동하지 않으면 Win7x64에서 충돌이 발생하기 쉽습니다. XPerf도 훌륭하게 수행되었지만 특정 종류의 응용 프로그램에서 좋은 판독을 얻는 데 필요한 샘플링 세부 사항에 대해 고통스럽게 느립니다.

지금 당장은 W7x64 환경에서 C ++ 코드를 프로파일 링하는 결정적인 옵션이 없다고 생각하지만 유용한 서비스를 수행하지 못하는 옵션이 있습니다.


먼저:

시간 샘플링 프로파일 러는 CPU 샘플링 프로파일 러보다 강력합니다. Windows 개발 도구에 익숙하지 않으므로 어떤 도구인지 알 수 없습니다. 대부분의 프로파일 러는 CPU 샘플링입니다.

CPU 샘플링 프로파일 러는 모든 N 명령어마다 스택 추적을받습니다.
이 기술은 코드에서 CPU 바인딩 된 부분을 보여줍니다. 그것이 응용 프로그램의 병목 인 경우 굉장합니다. 애플리케이션 스레드가 대부분의 시간을 뮤텍스를 놓고 싸우는 데 그리 좋지는 않습니다.

A time sampling profiler grabs a stack trace every N microseconds.
This technique will zero in on "slow" code. Whether the cause is CPU bound, blocking IO bound, mutex bound, or cache thrashing sections of code. In short what ever piece of code is slowing your application will standout.

So use a time sampling profiler if at all possible especially when profiling threaded code.

Second:

Sampling profilers generate gobs of data. The data is extremely useful, but there is often too much to be easily useful. A profile data visualizer helps tremendously here. The best tool I've found for profile data visualization is gprof2dot. Don't let the name fool you, it handles all kinds of sampling profiler output (AQtime, Sleepy, XPerf, etc). Once the visualization has pointed out the offending function(s), jump back to the raw profile data to get better hints on what the real cause is.

The gprof2dot tool generates a dot graph description that you then feed into a graphviz tool. The output is basically a callgraph with functions color coded by their impact on the application. alt text

A few hints to get gprof2dot to generate nice output.

  • I use a --skew of 0.001 on my graphs so I can easily see the hot code paths. Otherwise the int main() dominates the graph.
  • If you're doing anything crazy with C++ templates you'll probably want to add --strip. This is especially true with Boost.
  • I use OProfile to generate my sampling data. To get good output I need configure it to load the debug symbols from my 3rd party and system libraries. Be sure to do the same, otherwise you'll see that CRT is taking 20% of your application's time when what's really going on is malloc is trashing the heap and eating up 15%.

What happened when you tried random pausing? I use it all the time on a monster app. You said it did not give enough information, and you've suggested you need high resolution. Sometimes people need a little help in understanding how to use it.

What I do, under VS, is configure the stack display so it doesn't show me the function arguments, because that makes the stack display totally unreadable, IMO.

Then I take about 10 samples by hitting "pause" during the time it's making me wait. I use ^A, ^C, and ^V to copy them into notepad, for reference. Then I study each one, to try to figure out what it was in the process of trying to accomplish at that time.

If it was trying to accomplish something on 2 or more samples, and that thing is not strictly necessary, then I've found a live problem, and I know roughly how much fixing it will save.

There are things you don't really need to know, like precise percents are not important, and what goes on inside 3rd-party code is not important, because you can't do anything about those. What you can do something about is the rich set of call-points in code you can modify displayed on each stack sample. That's your happy hunting ground.

Examples of the kinds of things I find:

  • During startup, it can be about 30 layers deep, in the process of trying to extract internationalized character strings from DLL resources. If the actual strings are examined, it can easily turn out that the strings don't really need to be internationalized, like they are strings the user never actually sees.

  • During normal usage, some code innocently sets a Modified property in some object. That object comes from a super-class that captures the change and triggers notifications that ripple throughout the entire data structure, manipulating the UI, creating and desroying obects in ways hard to foresee. This can happen a lot - the unexpected consequences of notifications.

  • Filling in a worksheet row-by-row, cell-by-cell. It turns out if you build the row all at once, from an array of values, it's a lot faster.

P.S. If you're multi-threaded, when you pause it, all threads pause. Take a look at the call stack of each thread. Chances are, only one of them is the real culprit, and the others are idling.


I've had some success with AMD CodeAnalyst.


Do you have an MFC OnIdle function? In the past I had a near real-time app I had to fix that was dropping serial packets when set at 19.2K speed which a PentiumD should have been able to keep up with. The OnIdle function was what was killing things. I'm not sure if QT has that concept, but I'd check for that too.


Re the VS Profiler -- if it's generating such large files, perhaps your sampling interval is too frequent? Try lowering it, as you probably have enough samples anyway.

And ideally, make sure you're not collecting samples until you're actually exercising the problem area. So start with collection paused, get your program to do its "slow activity", then start collection. You only need at most 20 seconds of collection. Stop collection after this.

This should help reduce your sample file sizes, and only capture what is necessary for your analysis.


I have successfully used PurifyPlus for Windows. Although it is not cheap, IBM provides a trial version that is slightly crippled. All you need for profiling with quantify are pdb files and linking with /FIXED:NO. Only drawback: No support for Win7/64.


Easyprofiler - I haven't seen it mentioned here yet so not sure if you've looked at it already. It takes a slightly different approach in how it gathers metric data. A drawback to using its compile-time profile approach is you have to make changes to the code-base. Thus you'll need to have some idea of where the slow might be and insert profiling code there.

Going by your latest comments though, it sounds like you're at least making some headway. Perhaps this tool might provide some useful metrics for you. If nothing else it has some really purdy charts and pictures :P


Two more tool suggestions.

Luke Stackwalker has a cute name (even if it's trying a bit hard for my taste), it won't cost you anything, and you get the source code. It claims to support multi threaded programs, too. So it is surely worth a spin.

http://lukestackwalker.sourceforge.net/

Also Glowcode, which I've had pointed out to me as worth using:

http://www.glowcode.com/

Unfortunately I haven't done any PC work for a while, so I haven't tried either of these. I hope the suggestions are of help anyway.


Checkout XPerf

This is free, non-invasive and extensible profiler offered by MS. It was developed by Microsoft to profile Windows.


If you're suspicious of the event loop, could overriding QCoreApplication::notify() and dosome manual profiling (one or two maps of senders/events to counts/time)?

I'm thinking that you first log the frequency of event types, then examine those events more carefully (which object sends it, what does it contain, etc). Signals across threads are queued implicitly, so they end up in the event loop (as well explicit queued connections too, obviously).

We've done it to trap and report exceptions in our event handlers, so really, every event goes through there.

Just an idea.


Edit: I see now you mentioned this in your first post. Dammit, I never thought I'd be that guy.

You can use Pin to instrument your code with finer granularity. I think Pin would let you create a tool to count how many times you enter a function or how many clockticks you spend there, roughly emulating something like VTune or CodeAnalyst. Then you could strip down which functions get instrumented until your timing issues go away.


I can tell you what I use everyday.

a) AMD Code Analyst

  • It is easy, and it will give you a quick overview of what is happening. It will be ok for most of the time.
  • With AMD CPUs, it will tell you info about the cpu pipeline, but you only need this only if you have heavy loops, like in graphic engines, video codecs, etc.

b) VTune.

  • It is very well integrated in vs2008

  • after you know the hotspots, you need to sample not only time, but other things like cache misses, and memory usage. This is very important. Setup a sampling session, and edit the properties. I always sample for time, memory read/write, and cache misses (three different runs)

But more than the tool, you need to get experience with profiling. And that means understanding how the CPU/Memory/PCI works... so, this is my 3rd option

c) Unit testing

This is very important if you are developing a big application that needs huge performance. If you cannot split the app in some pieces, it will be difficult to track cpu usage. I dont test all the cases and classes, but I have hardcoded executions and input files with important features.

My advice is using random sampling in several small tests, and try to standardise a profile strategy.


I use xperf/ETW for all of my profiling needs. It has a steep learning curve but is incredibly powerful. If you are profiling on Windows then you must know xperf. I frequently use this profiler to find performance problems in my code and in other people's code.

In the configuration that I use it:

  • xperf grabs CPU samples from every core that is executing code every ms. The sampling rate can be increased to 8 KHz and the samples include user-mode and kernel code. This allows finding out what a thread is doing while it is running
  • xperf records every context switch (allowing for perfect reconstruction of how much time each thread uses), plus call stacks for when threads are switched in, plus call stacks for what thread readied another thread, allowing tracing of wait chains and finding out why a thread is not running
  • xperf records all file I/O from all processes
  • xperf records all disk I/O from all processes
  • xperf records what window is active, the CPU frequency, CPU power state, UI delays, etc.
  • xperf can also record all heap allocations from one process, all virtual allocations from all processes, and much more.

That's a lot of data, all on one timeline, for all processes. No other profiler on Windows can do that.

I have blogged extensively about how to use xperf/ETW. These blog posts, and some professionally quality training videos, can be found here: http://randomascii.wordpress.com/2014/08/19/etw-training-videos-available-now/

If you want to find out what might happen if you don't use xperf read these blog posts: http://randomascii.wordpress.com/category/investigative-reporting/ These are tales of performance problems I have found in other people's code, that should have been found by the developers. This includes mshtml.dll being loaded into the VC++ compiler, a denial of service in VC++'s find-in-files, thermal throttling in a surprising number of customer machines, slow single-stepping in Visual Studio, a 4 GB allocation in a hard-disk driver, a powerpoint performance bug, and more.


I just finished the first usable version of CxxProf, a portable manual instrumented profiling library for C++.

It fulfills the following goals:

  • Easy integration
  • Easily remove the lib during compile time
  • Easily remove the lib during runtime
  • Support for multithreaded applications
  • Support for distributed systems
  • Keep impact on a minimum

These points were ripped from the project wiki, have a look there for more details.

Disclaimer: Im the main developer of CxxProf


Just to throw it out, even though it's not a full-blown profiler: if all you're after is hung event loops that take long processing an event, an ad-hoc tool is simple matter in Qt. That approach could be easily expanded to keep track of how long did each event take to process, and what those events were, and so on. It's not a universal profiler, but an event-loop-centric one.

In Qt, all cross-thread signal-slot calls are delivered via the event loop, as are timers, network and serial port notifications, and all user interaction,. Thus, observing the event loops is a big step towards understanding where the application is spending its time.


DevPartner, originally developed by NuMega and now distributed by MicroFocus, was once the solution of choice for profiling and code analysis (memory and resource leaks for example). I haven't tried it recently, so I cannot assure you it will help you; but I once had excellent results with it, so that this is an alternative I do consider to re-install in our code quality process (they provide a 14 days trial)


though your os is win7,the programm cann't run under xp? how about profile it under xp and the result should be a hint for win7.


There are lots of profilers listed here and I've tried a few of them myself - however I ended up writing my own based on this:

http://code.google.com/p/high-performance-cplusplus-profiler/

It does of course require that you modify the code base, but it's perfect for narrowing down bottlenecks, should work on all x86s (could be a problem with multi-core boxes, i.e. it uses rdtsc, however - this is purely for indicative timing anyway - so I find it's sufficient for my needs..)


I use Orbit profiler, easy, open source and powerfull ! https://orbitprofiler.com/

참고URL : https://stackoverflow.com/questions/4394606/beyond-stack-sampling-c-profilers

반응형