Misusing FunctionProfiling for code coverage

thomas_braun
Posts: 507
Joined: 2009-10-07
Location: Germany

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
	if(a)
		a += 1
	else
		a += 2
	endif
 
End
 
Function run()
 
	variable i
 
	BeginFunctionProfiling(testTime = 1)
	for(i = 0; i < 1000000; i += 1)
		myTest()
	endfor
 	FuncProfilingModule#EndFunctionProfiling(normMode = 0, maxPct = 100)
End

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?

Thanks,
Thomas

[1]: http://ltp.sourceforge.net/coverage/lcov/output/example/methods/iterate....


JimProuty's picture
Posts: 619
Joined: 2007-07-19
Location: United States

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)
	endif
	Make/O/D/FREE/N=(desiredSamps) s.w
	s.tid= ThreadGroupCreate(1)
	ThreadStart s.tid, 0, DoProfiling(s.w, tms)
	s.testTime= StopMSTimer(-2)
End

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.


[ last edited September 12, 2017 - 12:07 ]

Back to top