========================================================================== Section 4 Notes ========================================================================== - 1. Build and run Criterion tests - 2. Using lcov for Code Coverage Analysis - 3. Using gdb for Debugging Adhoc Tests - 4. Using gdb for Debugging Criterion Tests - 5. Evaluating the Performance of C Programs * As in the tutorial, log into ecelinux from your laptop % ssh -X cb535@ecelinux-01.ece.cornell.edu % ssh -X cb535@ecelinux-02.ece.cornell.edu - don't forget to source the setup script! % source setup-ece2400.sh * Clone the tutorial repo % mkdir -p $HOME/ece2400 % cd $HOME/ece2400 % git clone git@github.com:cornell-ece2400/ece2400-tut3-c sec4 % cd sec4/tut3-gcd % TUTDIR=$PWD - if you have not uploaded your SSH key onto GitHub, then you may need to clone the repo like this: % mkdir -p $HOME/ece2400 % cd $HOME/ece2400 % git clone https://github.com/cornell-ece2400/ece2400-tut3-c sec4 % cd sec4/tut3-gcd % TUTDIR=$PWD -------------------------------------------------------------------------- 1. Build and run Criterion tests -------------------------------------------------------------------------- - last week we learned about using the ECE 2400 build system % cd $TUTDIR % mkdir build % cd build % ../configure % make gcd-test % ./gcd-test % make check - take a look at the TravisCI results - https://travis-ci.org/cornell-ece2400/ece2400-tut3-c -------------------------------------------------------------------------- 2. Using lcov for Code Coverage Analysis -------------------------------------------------------------------------- - lcov is a tool that will do code coverage analysis - code coverage analysis tells you how many times each line in your code has been executed and which lines have never been executed - if a line has never been executed then it has not been tested! - you need to compile your program specially to enable code coverage - by default the build system sets all of the correct compiler flags - usually good to do code coverage analysis from a clean build % cd $TUTDIR/build % make clean % make coverage % firefox coverage-html/index.html - browse to see the coverage analsysi for src/gcd.c - take a look at the Codecov.io results - https://codecov.io/gh/cornell-ece2400/ece2400-tut3-c - the return -1 statement is never executed! - add a new test case for negative inputs Test( gcd, negative ) { cr_assert_eq( gcd( -5, 15 ), -1 ); cr_assert_eq( gcd( 5, -15 ), -1 ); cr_assert_eq( gcd( 5, -15 ), -1 ); } - rerun the tests and verify everything passes % cd $TUTDIR/build % make check - rerun code coverage analysis % cd $TUTDIR/build % make clean % make coverage % firefox coverage-html/index.html - now we have 100% coverage! - commit and push the results (students can't do this, just cbatten) % git xstatus % git xadd % git push - take a look at the Codecov.io results - https://codecov.io/gh/cornell-ece2400/ece2400-tut3-c -------------------------------------------------------------------------- 3. Using gdb for Debugging Adhoc Tests -------------------------------------------------------------------------- - gdb enables stepping through your code one statement at a time - gdb essentially enables executing your code just like we do by hand - let's start gdb and run the adhoc test within gdb % cd $TUTDIR/build % make gcd-adhoc-test % gdb ./gcd-adhoc-test (gdb) run - let's set a "breakpoint" at the main function with the "break" command - a breakpoint tell's gdb to stop when it reaches that point in the code (gdb) break main (gdb) run - we can use the "step" to step through each statement one at a time (gdb) step (gdb) step (gdb) ... - gdb can print out variables, just like with our "stack frame" diagrams (gdb) print x (gdb) print y - we can continue to the next breakpoint or end of the program (gdb) contine - let's set a breakpoint on the statemen if ( x < y ) in gcd.c (line 21) (gdb) break gcd.c:21 - let's run until we reach the breakpoint at main, continue into the gcd function, print x and y, continue, and repeat; you should write down x and y everytime through the loop (gdb) run (gdb) continue (gdb) print x (gdb) print y (gdb) continue (gdb) ... - if you compare what you wrote down with the table we made in lecture, we are essentially doing the exact same thing (gdb) quit -------------------------------------------------------------------------- 4. Using gdb for Debugging Criterion Tests -------------------------------------------------------------------------- - Using gdb with Criterion tests is a bit more involved - Criterion runs each test in its own isolated process - This _greatly_ simplifies dealing with segfaults % cd $TUTDIR/build % make gcd-test % gdb ./gcd-test -x ../scripts/criterion.gdb - set breakpoints like before (gdb) break gcd.c:21 (gdb) run (gdb) print x - print won't work, need to do an extra step (gdb) info inferior (gdb) inferior 2 - now you can print out variables since you are in the "test process" (gdb) print x (gdb) print y (gdb) continue (gdb) ... (gdb) quit -------------------------------------------------------------------------- 5. Evaluating the Performance of C Programs -------------------------------------------------------------------------- - take a look at src/gcd-eval.c #include #include ... // Start tracking time struct timeval start; gettimeofday( &start, NULL ); // Run for at least a few seconds to avoid precision issues for ( int j = 0; j < nsubtrials; j++ ) { for ( int k = 0; k < dataset_size; k++ ) { ... run the experiment ... } } // Stop tracking time struct timeval end; gettimeofday( &end, NULL ); // Calculate elapsed time double elapsed = (end.tv_sec - start.tv_sec) + ( (end.tv_usec - start.tv_usec) / 1000000.0 ); elapsed_avg += elapsed; printf( "Elapsed time for trial %d is %f\n", i, elapsed ); - let's build and run the evaluation program % cd $TUTDIR/build % make gcd-eval % ./gcd-eval - problem is that this is the _debug_ build - includes overheads due to debugging - let's create an evaluation build % cd $TUTDIR % mkdir build-eval % cd build-eval % ../configure --enable-eval % make gcd-eval % ./gcd-eval - notice the different command line arguments! - notice gcd is much faster now - can run all evaluation programs with a single target % make eval