Implementation Issues

Stack Traces

Accurate stack traces are needed during profiling since we group events by call context and dynamic instance. Without accurate traces, diagnostics may be hard to interpret. For instance, when giving advice to the user it is imperative to reference application code, not library code.

Currently we are using the libc backtrace routine to get stack traces. _GLIBCXX_PROFILE_STACK_DEPTH can be set to 0 if you are willing to give up call context information, or to a small positive value to reduce run time overhead.

Symbolization of Instruction Addresses

The profiling and analysis phases use only instruction addresses. An external utility such as addr2line is needed to postprocess the result. We do not plan to add symbolization support in the profile extension. This would require access to symbol tables, debug information tables, external programs or libraries and other system dependent information.

Concurrency

Our current model is simplistic, but precise. We cannot afford to approximate because some of our diagnostics require precise matching of operations to container instance and call context. During profiling, we keep a single information table per diagnostic. There is a single lock per information table.

Using the Standard Library in the Instrumentation Implementation

As much as we would like to avoid uses of libstdc++ within our instrumentation library, containers such as unordered_map are very appealing. We plan to use them as long as they are named properly to avoid ambiguity.

Malloc Hooks

User applications/libraries can provide malloc hooks. When the implementation of the malloc hooks uses stdlibc++, there can be an infinite cycle between the profile mode instrumentation and the malloc hook code.

We protect against reentrance to the profile mode instrumentation code, which should avoid this problem in most cases. The protection mechanism is thread safe and exception safe. This mechanism does not prevent reentrance to the malloc hook itself, which could still result in deadlock, if, for instance, the malloc hook uses non-recursive locks. XXX: A definitive solution to this problem would be for the profile extension to use a custom allocator internally, and perhaps not to use libstdc++.

Construction and Destruction of Global Objects

The profiling library state is initialized at the first call to a profiling method. This allows us to record the construction of all global objects. However, we cannot do the same at destruction time. The trace is written by a function registered by atexit, thus invoked by exit.