Performance monitoring
In this section, we will build upon the previous example and add features that allow monitoring the performance of the MARTe2 application, namely the timing of the GAMs and of the thread cycle time.
We want to monitor:
The cycle time of the thread executing the GAMs. This is the time between two consecutive executions of the thread. It is expected to be constant and equal to the inverse of the
Frequencyparameter of theGAMTimer.The execution time of the GAMs. This is the time taken by the GAMs to execute their logic.
The time it takes to copy from the DataSource to the GAMs. This includes any overhead of the DataSource (e.g. to access the hardware) and the time taken to copy the data from the DataSource to the GAMs.
The time it takes to copy from the GAMs to the DataSources. This includes any overhead of the DataSource (e.g. to access the hardware) and the time taken to copy the data from the GAMs to the DataSources.
All the times are absolute with respect to the start of the real-time cycle and are measured in microseconds.
Timing diagram for the mass-spring-damper system.
Note
The GAM that synchronises with the DataSource pacing the thread waits during its read phase for the trigger to arrive. Consequently, this provides an indirect measurement of the thread’s available free time (the higher, the better).
Note
The cycle time is measured between the end of two consecutive cycles, rather than between the thread’s synchronisation points (i.e. when the LinuxTimer is triggered). While this is typically not an issue, if the GAM load varies over time it may result in a cycle time that appears non-constant, even when the synchronisation trigger is very stable.
Note
Since the measurements are taken during the cycle, the execution order of the GAM that reads from the Timing DataSource determines whether the reported times for other GAMs correspond to the current or the previous cycle. If the Timing GAM executes before the others, the reported times will refer to the previous cycle, but will remain consistent across all GAMs.
1 +Thread1 = {
2 Class = RealTimeThread
3 CPUs = 0x1
4 Functions = {GAMPerfMonitor GAMTimer GAMReference GAMController GAMSpringMass GAMDisplay}
5 }
Running the application
Start the application with:
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-3.cfg -l RealTimeLoader -s State1
Once the application is running, inspect the screen output and verify that the log shows the cycle time and the execution times of the GAMs. The log should show entries similar to the following:
$ [Information - LoggerBroker.cpp:152]: Thread1CycleTime [0:0]:9992
$ [Information - LoggerBroker.cpp:152]: GAMTimer_ReadTime [0:0]:9878
$ [Information - LoggerBroker.cpp:152]: GAMTimer_ExecTime [0:0]:9878
$ [Information - LoggerBroker.cpp:152]: GAMTimer_WriteTime [0:0]:9878
$ [Information - LoggerBroker.cpp:152]: GAMReference_ExecTime [0:0]:9879
$ [Information - LoggerBroker.cpp:152]: GAMReference_WriteTime [0:0]:9879
$ [Information - LoggerBroker.cpp:152]: GAMController_ReadTime [0:0]:9879
$ [Information - LoggerBroker.cpp:152]: GAMController_ExecTime [0:0]:9879
$ [Information - LoggerBroker.cpp:152]: GAMController_WriteTime [0:0]:9879
$ [Information - LoggerBroker.cpp:152]: GAMDisplay_ReadTime [0:0]:9896
$ [Information - LoggerBroker.cpp:152]: GAMDisplay_ExecTime [0:0]:9897
$ [Information - LoggerBroker.cpp:152]: GAMDisplay_WriteTime [0:0]:9991
...
Exercises
Ex. 1: Add the missing times
Edit the file
../Configurations/MassSpring/RTApp-MassSpring-4.cfgand add theRead,Exec, andWritetimes for the two missing GAMs.Verify that the two missing times are now present in the logger output.
./MARTeApp.sh -f ../Configurations/MassSpring/RTApp-MassSpring-4.cfg -l RealTimeLoader -s State1
Solution
The solution is to add the missing signals in the GAMPerMonitor and GAMDisplay.
1 +GAMPerfMonitor = {
2 Class = IOGAM
3 InputSignals = {
4 GAMSpringMass_ReadTime = {
5 DataSource = Timings
6 Type = uint32
7 }
8 GAMSpringMass_ExecTime = {
9 DataSource = Timings
10 Type = uint32
11 }
12 GAMSpringMass_WriteTime = {
13 DataSource = Timings
14 Type = uint32
15 }
16 GAMPerfMonitor_ReadTime = {
17 DataSource = Timings
18 Type = uint32
19 }
20 GAMPerfMonitor_ExecTime = {
21 DataSource = Timings
22 Type = uint32
23 }
24 GAMPerfMonitor_WriteTime = {
25 DataSource = Timings
26 Type = uint32
27 }
28 OutputSignals = {
29 GAMSpringMass_ReadTime = {
30 DataSource = DDB1
31 Type = uint32
32 }
33 GAMSpringMass_ExecTime = {
34 DataSource = DDB1
35 Type = uint32
36 }
37 GAMSpringMass_WriteTime = {
38 DataSource = DDB1
39 Type = uint32
40 }
41 GAMPerfMonitor_ReadTime = {
42 DataSource = DDB1
43 Type = uint32
44 }
45 GAMPerfMonitor_ExecTime = {
46 DataSource = DDB1
47 Type = uint32
48 }
49 GAMPerfMonitor_WriteTime = {
50 DataSource = DDB1
51 Type = uint32
52 }
53 +GAMDisplay = {
54 Class = IOGAM
55 InputSignals = {
56 GAMSpringMass_ReadTime = {
57 DataSource = DDB1
58 Type = uint32
59 }
60 GAMSpringMass_ExecTime = {
61 DataSource = DDB1
62 Type = uint32
63 }
64 GAMSpringMass_WriteTime = {
65 DataSource = DDB1
66 Type = uint32
67 }
68 GAMPerfMonitor_ReadTime = {
69 DataSource = DDB1
70 Type = uint32
71 }
72 GAMPerfMonitor_ExecTime = {
73 DataSource = DDB1
74 Type = uint32
75 }
76 GAMPerfMonitor_WriteTime = {
77 DataSource = DDB1
78 Type = uint32
79 }
80 OutputSignals = {
81 GAMSpringMass_ReadTime = {
82 DataSource = Display
83 Type = uint32
84 }
85 GAMSpringMass_ExecTime = {
86 DataSource = Display
87 Type = uint32
88 }
89 GAMSpringMass_WriteTime = {
90 DataSource = Display
91 Type = uint32
92 }
93 GAMPerfMonitor_ReadTime = {
94 DataSource = Display
95 Type = uint32
96 }
97 GAMPerfMonitor_ExecTime = {
98 DataSource = Display
99 Type = uint32
100 }
101 GAMPerfMonitor_WriteTime = {
102 DataSource = Display
103 Type = uint32
104 }