NXC Profiler
Back to projects index
| Project Title | Author / Institution |
|---|---|
| NXC Profiler (Weblink) | Linus Atorf (Toolbox Developer Member), Germany |
This particular page is not directly affiliated with the RWTH - Mindstorms NXT Toolbox
|
NXC Profiler
On this page I present a preview / proof-of-concept of a profiler-like tool for NXC. Fore more details and concepts, see here: http://forums.nxtasy.org/index.php?showtopic=4496
Sourcecode for all of this can be found here.
- Profiler01.nxc is the NXC part of the demo, it has to be included by the application to be profiled.
- sample.nxc and sample2 .nxc are example applications with profiler-code included.
- After running the profiled program, the results file has to be manually retrieved from the NXT and copied into the directory of the analyzer.
- AnalyzeNXCProfile.py is the main program of the analyzer (written in Python).
- testit.bat will generate a HTML version of the sample files in that directory (same with testit2.bat).
Below you can see two example outputs from the current version (December 12th, 2009). You can distinguish profiled sections from non-profiled ones. At the bottom there is a secion with code that never ran (I tricked the Analyzer by faking some lines inside a block-comment which is not yet supported). The "time" column shows calls that took at least 1ms added up (that's why it's only a lower boundary for execution time). If there were calls where the firmware didn't tick (i.e. calls that definitely took less than 1ms), it's indicated here as percentage.
The 3rd column shows time per call. Again, it's a lower boundary. The bigger this time, the more accurate it should be. If the profiler should've encountered sections which took less than 1ms to execute, but not all the times, it's shown here with frequencies in percent.
Look below for 2 examples. The first one is a real-world case. As you can see, the Ultrasonic sensor never found a target in my sample run — that's valuable debug information. The 2nd example is from my old benchmark and much more artificial — but without looking at the LCD screen, you can see that "shifting" operations are quite expensive, for example.
Currently all of this is proof-of-concept and work in progress. Anyway, enjoy!
Linus Atorf
| File summary | |
|---|---|
| Source file name: | sample2.nxc |
| Profile results file: | sample2.prf |
| __FIRMWARE_VERSION: | 120 |
| __ENHANCED_FIRMWARE: | no |
| Runtime summary | |
| Total program runtime (until STOP): | 5.58 seconds |
| Profiler runtime (between START and STOP): | 5.55 seconds |
| Sections runtime (sum of all sections > 1ms): | 5.19 seconds |
| Profiled source code | |||
|---|---|---|---|
| Calls | Time | Time / Call | Code |
| Not profiled | //#!C /* % % Another example to demonstrate the NXC-Profiler! % % see http://www.mindstorms.rwth-aachen.de/trac/wiki/NXCProfiler % and http://forums.nxtasy.org/index.php?showtopic=4496 % % Signature % Author: Linus Atorf (see AUTHORS) % Date: 2009/12/12 % License: GPLv3 % % % *********************************************************************************************** % * This file is part of the NXC Profiler. * % * * % * The NXC Profiler is free software: you can redistribute it and/or modify * % * it under the terms of the GNU General Public License as published by the Free Software * % * Foundation, either version 3 of the License, or (at your option) any later version. * % * * % * The NXC Profiler is distributed in the hope that it will be useful, * % * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * % * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * % * * % * You should have received a copy of the GNU General Public License along with the * % * NXC Profiler. If not, see <http://www.gnu.org/licenses/>. * % *********************************************************************************************** */ // SET UP THE PROFILER // comment this out to silently disable profiling without any side effects! #define PROFILER_ENABLE // how many times did we use PROFILER_BEGINSECTION (and ENDSECTION) #define PROFILER_MAXSECTIONS 7 // name of the binary results file we later analyze #define PROFILER_RESULTSFILE "sample2.prf" // this does all the magic :-) #include "Profiler01.nxc" #define USPORT S1 task main () { int distance; SetSensorLowspeed(USPORT); PROFILER_START(); // main loop while (!ButtonPressed(BTNCENTER, false)) { | ||
| 173 | > 5.190 s (94%) | > 30.0 ms | PROFILER_BEGINSECTION(0); distance = SensorUS(USPORT); PROFILER_ENDSECTION(0); |
| Not profiled | |||
| 173 | > 0.003 s (0%) by 1% of the calls | > 1.0 ms (in 1%) < 1.0 ms (in 98%) | PROFILER_BEGINSECTION(3); // empty... PROFILER_ENDSECTION(3); |
| Not profiled | if (distance < 100) { | ||
| Never executed | PROFILER_BEGINSECTION(1); PlayTone(1000, 100); PROFILER_ENDSECTION(1); | ||
| Not profiled | } else { | ||
| 173 | > 0.000 s (0%) by 0% of the calls | < 1 ms | PROFILER_BEGINSECTION(2); PlayTone(200, 100); PROFILER_ENDSECTION(2); |
| Not profiled | }//end if }//end while PROFILER_STOP(); }// end task | ||
| File summary | |
|---|---|
| Source file name: | sample.nxc |
| Profile results file: | sample.prf |
| __FIRMWARE_VERSION: | 120 |
| __ENHANCED_FIRMWARE: | no |
| Runtime summary | |
| Total program runtime (until STOP): | 17.29 seconds |
| Profiler runtime (between START and STOP): | 17.28 seconds |
| Sections runtime (sum of all sections > 1ms): | 9.11 seconds |
| Profiled source code | |||
|---|---|---|---|
| Calls | Time | Time / Call | Code |
| Not profiled | //#!C /* % % Example to demonstrate the NXC-Profiler! % % see http://forums.nxtasy.org/index.php?showtopic=4496 % % % Signature % Author: Linus Atorf (see AUTHORS) % Date: 2009/12/07 % License: GPLv3 % % % *********************************************************************************************** % * This file is part of the NXC Profiler. * % * * % * The NXC Profiler is free software: you can redistribute it and/or modify * % * it under the terms of the GNU General Public License as published by the Free Software * % * Foundation, either version 3 of the License, or (at your option) any later version. * % * * % * The NXC Profiler is distributed in the hope that it will be useful, * % * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * % * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * % * * % * You should have received a copy of the GNU General Public License along with the * % * NXC Profiler. If not, see <http://www.gnu.org/licenses/>. * % *********************************************************************************************** */ // SET UP THE PROFILER // comment this out to silently disable profiling without any side effects! #define PROFILER_ENABLE // how many times did we use PROFILER_BEGINSECTION (and ENDSECTION) #define PROFILER_MAXSECTIONS 7 // name of the binary results file we later analyze #define PROFILER_RESULTSFILE "sample.prf" // this does all the magic :-) #include "Profiler01.nxc" // smaller value for quicker testing // greater value for more accurate results #define TESTITERATIONS 2000 // constants #define OPSPERTESTLOOP 5 #define ARRAYSIZE 200 task main () { PROFILER_START(); long longI; long longA = 234; long longB = -243534554; long longC; long longD; long long1 = 1; long longArray[ARRAYSIZE]; int intI; int intA = 23; int intB = -2345; int intC; int intD; int int1 = 1; long StartTick; long OpsPerSec; TextOut(0, LCD_LINE1, "testing...", true); | ||
| 1 | > 0.760 s (4%) | > 760.0 ms | PROFILER_BEGINSECTION(0); // --- Test INT ADDITIONS StartTick = CurrentTick(); for (intI = 0; intI < TESTITERATIONS; intI++) { intC = intA + intB; intA = intC - intB; intC = intA + intB; intA = intC - intB; intC = intA + intB; }//end for PROFILER_ENDSECTION(0); |
| Not profiled | OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "int +-", true); NumOut (0, LCD_LINE3, OpsPerSec); until (ButtonPressed(BTNCENTER, false)); TextOut(0, LCD_LINE1, "testing...", true); | ||
| 1 | > 0.658 s (4%) | > 658.0 ms | PROFILER_BEGINSECTION(1); // --- Test LONG ADDITIONS StartTick = CurrentTick(); for (longI = 0; longI < TESTITERATIONS; longI++) { longC = longA + longB; longA = longC - longB; longC = longA + longB; longA = longC - longB; longC = longA + longB; }//end for PROFILER_ENDSECTION(1); |
| Not profiled | OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "long +-", true); NumOut (0, LCD_LINE3, OpsPerSec); until (ButtonPressed(BTNCENTER, false)); TextOut(0, LCD_LINE1, "testing...", true); // --- Test LONG MULTIPLICATIONS | ||
| 1 | > 0.684 s (4%) | > 684.0 ms | PROFILER_BEGINSECTION(2); StartTick = CurrentTick(); for (longI = 0; longI < TESTITERATIONS; longI++) { longC = longA * longB; longD = longA * 2; longC = longD * 5; longD = longB * (-35); longC = longB * longA; }//end for PROFILER_ENDSECTION(2); |
| Not profiled | OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "long *", true); NumOut (0, LCD_LINE3, OpsPerSec); until (ButtonPressed(BTNCENTER, false)); TextOut(0, LCD_LINE1, "testing...", true); // --- Test INT SHIFTS | ||
| 1 | > 2.715 s (16%) | > 2715.0 ms | PROFILER_BEGINSECTION(3); StartTick = CurrentTick(); for (intI = 0; intI < TESTITERATIONS; intI++) { intC = intA << 2; intD = intB >> 1; intC = intB << 8; intD = intA >> 4; intC = intA << int1; }//end while PROFILER_ENDSECTION(3); |
| Not profiled | OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "int <<", true); NumOut (0, LCD_LINE3, OpsPerSec); until (ButtonPressed(BTNCENTER, false)); TextOut(0, LCD_LINE1, "testing...", true); // --- Test LONG SHIFTS | ||
| 1 | > 2.650 s (15%) | > 2650.0 ms | PROFILER_BEGINSECTION(4); StartTick = CurrentTick(); for (longI = 0; longI < TESTITERATIONS; longI++) { longC = longA << 2; longD = longB >> 1; longC = longB << 8; longD = longA >> 4; longC = longA << long1; }//end while PROFILER_ENDSECTION(4); |
| Not profiled | OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "long <<", true); NumOut (0, LCD_LINE3, OpsPerSec); until (ButtonPressed(BTNCENTER, false)); TextOut(0, LCD_LINE1, "testing...", true); // --- Test VARIOUS CALLS StartTick = CurrentTick(); for (longI = 0; longI < (TESTITERATIONS * 3); longI++) { | ||
| 6000 | > 1.640 s (9%) by 27% of the calls | > 1.0 ms (in 27%) < 1.0 ms (in 72%) | PROFILER_BEGINSECTION(5); longD = MotorTachoCount(OUT_A); longD = CurrentTick(); longC = MotorTachoCount(OUT_B); longC = CurrentTick(); longD = MotorTachoCount(OUT_C); PROFILER_ENDSECTION(5); |
| Not profiled | }//end while OpsPerSec = (TESTITERATIONS * 1000 * OPSPERTESTLOOP * 3) / (CurrentTick() - StartTick); TextOut(0, LCD_LINE1, "tick/tachocount calls", true); NumOut (0, LCD_LINE3, OpsPerSec); PROFILER_STOP(); until (ButtonPressed(BTNCENTER, false)); // --- Done /* DIRTY DIRTY HACK TEST this code was not profiled this is a quick hack... bad bad... | ||
| Never executed | PROFILER_BEGINSECTION(6); // something // something // this should never ever be executed // different color highlighting? PROFILER_ENDSECTION(6); | ||
| Not profiled | */ }//end task | ||

This particular page is not directly affiliated with the RWTH - Mindstorms NXT Toolbox