Misusing FunctionProfiling for code coverage

I'm trying to get code coverage information for my igor code. The end result I would like to get is a very slim version of [1].

The idea is that it is easy to see with code coverage which parts of a function have tests associated with them and which not.

I've tried using the FunctionProfiling code a la

#include <FunctionProfiling>

Function MyTest()

    variable a
        a += 1
        a += 2


Function run()
    variable i

    BeginFunctionProfiling(testTime = 1)
    for(i = 0; i < 1000000; i += 1)
    FuncProfilingModule#EndFunctionProfiling(normMode = 0, maxPct = 100)

which gives

[...] ******************************************************************************************* Function: UTF_Main.ipf MyTest; Percent total 48% ******************************************************************************************* [17]** |Function MyTest() [00] | [00] | variable a [03]* | if(a) [00] | a += 1 [03]* | else [22]** | a += 2 [03]* | endif [00] | [01]* |End [...]

In principle this holds the information I want (the if branch is not executed but the else part is). The main drawbacks here are that I don't know how often I have to repeat it to get reasonable results (1e6 is already ridiculously large) and that it does seem not so reliable ("variable a" is never executed).

Is there something obvious I'm missing? Or does the Igor compiler not work how I seem to expect it?


[1]: http://ltp.sourceforge.net/coverage/lcov/output/example/methods/iterate…
Variables' default value is 0, so there's that (Strings' default value is NULL)

The profiling code runs in a separate thread that only periodically samples where the main thread's "program counter" is.

If the code being profiled runs very quickly, like your code does, too few samples are taken to create meaningful statistics.

The sampling interval is computed in StartProfiling():

Static Function StartProfiling(s, tmax)
    STRUCT MyProfilingStuff &s
    Variable tmax   // time in seconds the test is expected to take (needed if > 100)
    Variable desiredSamps= 100000                       // big enough for 100 sec at 1ms sampling rate
    Variable tms= round(1000*tmax/desiredSamps)     // milliseconds to sleep between samples
    if( tms<1 )
        tms= 1
    elseif( tms>100 )
        tms= 100
        desiredSamps= round(tmax*1000/tms)
    Make/O/D/FREE/N=(desiredSamps) s.w
    s.tid= ThreadGroupCreate(1)
    ThreadStart s.tid, 0, DoProfiling(s.w, tms)
    s.testTime= StopMSTimer(-2)

You can see that the minimum sampling rate is 1 millisecond. run() with the loop max set to 1000000 runs in 16.4576 microseconds.

--Jim Prouty
Software Engineer, WaveMetrics, Inc.