JuliaLang/julia — pull request #1865 by timholy (2013-01-02 12:26:45+00:00)
Title: WIP: towards a sampling profiler

I've started working on a sampling profiler. The basic idea is very simple: as you run your julia code, periodically take a "backtrace snapshot" that captures the current line # and calling stack. By analyzing this information, one gets a statistical sense for the bottlenecks in code, since the same functions or lines show up repeatedly.

This is intended as a supplement to our existing "intrumenting profiler". A sampling profiler does not give the kind of detailed line-by-line information obtained from an instrumenting profiler, but in principle it does have a couple of its own advantages:

1. It may not require any modification to the code; the compiler is free to optimize without worrying about instrumentation lines.
2. It's not necessary to wrap code in "@profile begin...end", and consequently one can even profile code all the way down into Base.
3. If it takes ~30 microseconds to take a backtrace, and you take one every millisecond, there is little or no performance overhead. Of course, the more rarely you take snapshots, the worse your statistics (or the longer your run times need to be).

The catch, of course, is that it doesn't yet work. The biggest problem is that the backtrace seems to always come back the same. I'm worried that the backtrace is effectively being run in a separate thread and that I'm just backtracing the profiling code, rather than what's currently running in Julia; assuming that's the problem, I'm not quite sure how to solve it (libunwind-ptrace?). Avoiding this outcome is the entire reason I did this in C rather than trying an implementation in terms of Tasks, but it seems this did not suffice.

A smaller issue is that the backtrace parsing is yielding NULL function pointers, and again I'm not sure why. (I separated out the parsing and the storage of the pointers to try to improve efficiency during the run.)

The long-term idea is that much of this might live in a separate package, but for ease of development I'm coding it inside the Julia repository for now (this simplifies the Makefile issues). It's also possible that this would need to be so tightly integrated with Julia that it shouldn't be a separate package.

If you want to play with this, you'll need this gist: https://gist.github.com/4434156

Demo (uses the gist):
```julia
julia> require("ProfNew.jl"); using ProfNew

julia> @sprofile testlen()
length = 270
length = 375
length = 410
length = 445
length = 485
1493.063943655766

julia> p, n = parse_backtrace()
buf => [0x00007f4ac6748cbd, 0x00007f4ac6ae268a, 0x00007f4ac77b2e9a, 0x00007f4ac624e40c]
n = 4
data[i] = 7f4ac6748cbd
data[i] = 7f4ac6ae268a
data[i] = 7f4ac77b2e9a
data[i] = 7f4ac624e40c
({},[104, 104, 104, 104])
```