00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackEngineProfiling.h"
00021 #include "JackGraphManager.h"
00022 #include "JackClientControl.h"
00023 #include "JackClientInterface.h"
00024 #include "JackTime.h"
00025
00026 namespace Jack
00027 {
00028
00029 JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0)
00030 {
00031 jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
00032
00033
00034 memset(fProfileTable, 0, sizeof(fProfileTable));
00035 }
00036
00037 JackEngineProfiling::~JackEngineProfiling()
00038 {
00039 FILE* file = fopen("JackEngineProfiling.log", "w");
00040 char buffer[1024];
00041
00042 jack_info("Write server and clients timing data...");
00043
00044 if (file == NULL) {
00045 jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
00046 } else {
00047
00048
00049 for (int i = 2; i < TIME_POINTS; i++) {
00050
00051
00052 long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
00053 long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
00054
00055 if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
00056 continue;
00057
00058
00059 fprintf(file, "%ld \t %ld \t", d1, d2);
00060
00061
00062 for (unsigned int j = 0; j < fMeasuredClient; j++) {
00063
00064 int ref = fIntervalTable[j].fRefNum;
00065
00066
00067 if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
00068
00069 long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
00070 long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
00071 long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
00072
00073
00074 fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t",
00075 ref,
00076 ((d5 > 0) ? d5 : 0),
00077 ((d6 > 0) ? d6 : 0),
00078 ((d7 > 0) ? d7 : 0),
00079 ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0),
00080 ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0),
00081 fProfileTable[i].fClientTable[ref].fStatus);
00082 } else {
00083 fprintf(file, "\t \t \t \t \t \t \t");
00084 }
00085 }
00086
00087
00088 fprintf(file, "\n");
00089 }
00090 }
00091
00092
00093 file = fopen("Timing1.plot", "w");
00094
00095 if (file == NULL) {
00096 jack_error("JackEngineProfiling::Save cannot open Timing1.log file");
00097 } else {
00098
00099 fprintf(file, "set grid\n");
00100 fprintf(file, "set title \"Audio driver timing\"\n");
00101 fprintf(file, "set xlabel \"audio cycles\"\n");
00102 fprintf(file, "set ylabel \"usec\"\n");
00103 fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
00104
00105 fprintf(file, "set output 'Timing1.pdf\n");
00106 fprintf(file, "set terminal pdf\n");
00107
00108 fprintf(file, "set grid\n");
00109 fprintf(file, "set title \"Audio driver timing\"\n");
00110 fprintf(file, "set xlabel \"audio cycles\"\n");
00111 fprintf(file, "set ylabel \"usec\"\n");
00112 fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
00113
00114 fclose(file);
00115 }
00116
00117
00118 file = fopen("Timing2.plot", "w");
00119
00120 if (file == NULL) {
00121 jack_error("JackEngineProfiling::Save cannot open Timing2.log file");
00122 } else {
00123
00124 fprintf(file, "set grid\n");
00125 fprintf(file, "set title \"Driver end date\"\n");
00126 fprintf(file, "set xlabel \"audio cycles\"\n");
00127 fprintf(file, "set ylabel \"usec\"\n");
00128 fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
00129
00130 fprintf(file, "set output 'Timing2.pdf\n");
00131 fprintf(file, "set terminal pdf\n");
00132
00133 fprintf(file, "set grid\n");
00134 fprintf(file, "set title \"Driver end date\"\n");
00135 fprintf(file, "set xlabel \"audio cycles\"\n");
00136 fprintf(file, "set ylabel \"usec\"\n");
00137 fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
00138
00139 fclose(file);
00140 }
00141
00142
00143 if (fMeasuredClient > 0) {
00144 file = fopen("Timing3.plot", "w");
00145 if (file == NULL) {
00146 jack_error("JackEngineProfiling::Save cannot open Timing3.log file");
00147 } else {
00148
00149 fprintf(file, "set multiplot\n");
00150 fprintf(file, "set grid\n");
00151 fprintf(file, "set title \"Clients end date\"\n");
00152 fprintf(file, "set xlabel \"audio cycles\"\n");
00153 fprintf(file, "set ylabel \"usec\"\n");
00154 fprintf(file, "plot ");
00155 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00156 if (i == 0) {
00157 if (i + 1 == fMeasuredClient) {
00158 sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
00159 ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00160 } else {
00161 sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
00162 ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00163 }
00164 } else if (i + 1 == fMeasuredClient) {
00165 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00166 } else {
00167 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
00168 }
00169 fprintf(file, buffer);
00170 }
00171
00172 fprintf(file, "\n unset multiplot\n");
00173 fprintf(file, "set output 'Timing3.pdf\n");
00174 fprintf(file, "set terminal pdf\n");
00175
00176 fprintf(file, "set multiplot\n");
00177 fprintf(file, "set grid\n");
00178 fprintf(file, "set title \"Clients end date\"\n");
00179 fprintf(file, "set xlabel \"audio cycles\"\n");
00180 fprintf(file, "set ylabel \"usec\"\n");
00181 fprintf(file, "plot ");
00182 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00183 if (i == 0) {
00184 if ((i + 1) == fMeasuredClient) {
00185 sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
00186 ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00187 } else {
00188 sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
00189 ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00190 }
00191 } else if ((i + 1) == fMeasuredClient) {
00192 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
00193 } else {
00194 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
00195 }
00196 fprintf(file, buffer);
00197 }
00198
00199 fclose(file);
00200 }
00201 }
00202
00203
00204 if (fMeasuredClient > 0) {
00205 file = fopen("Timing4.plot", "w");
00206
00207 if (file == NULL) {
00208 jack_error("JackEngineProfiling::Save cannot open Timing4.log file");
00209 } else {
00210
00211 fprintf(file, "set multiplot\n");
00212 fprintf(file, "set grid\n");
00213 fprintf(file, "set title \"Clients scheduling latency\"\n");
00214 fprintf(file, "set xlabel \"audio cycles\"\n");
00215 fprintf(file, "set ylabel \"usec\"\n");
00216 fprintf(file, "plot ");
00217 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00218 if ((i + 1) == fMeasuredClient)
00219 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
00220 else
00221 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
00222 fprintf(file, buffer);
00223 }
00224
00225 fprintf(file, "\n unset multiplot\n");
00226 fprintf(file, "set output 'Timing4.pdf\n");
00227 fprintf(file, "set terminal pdf\n");
00228
00229 fprintf(file, "set multiplot\n");
00230 fprintf(file, "set grid\n");
00231 fprintf(file, "set title \"Clients scheduling latency\"\n");
00232 fprintf(file, "set xlabel \"audio cycles\"\n");
00233 fprintf(file, "set ylabel \"usec\"\n");
00234 fprintf(file, "plot ");
00235 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00236 if ((i + 1) == fMeasuredClient)
00237 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
00238 else
00239 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
00240 fprintf(file, buffer);
00241 }
00242 fclose(file);
00243 }
00244 }
00245
00246
00247 if (fMeasuredClient > 0) {
00248 file = fopen("Timing5.plot", "w");
00249
00250 if (file == NULL) {
00251 jack_error("JackEngineProfiling::Save cannot open Timing5.log file");
00252 } else {
00253
00254 fprintf(file, "set multiplot\n");
00255 fprintf(file, "set grid\n");
00256 fprintf(file, "set title \"Clients duration\"\n");
00257 fprintf(file, "set xlabel \"audio cycles\"\n");
00258 fprintf(file, "set ylabel \"usec\"\n");
00259 fprintf(file, "plot ");
00260 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00261 if ((i + 1) == fMeasuredClient)
00262 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
00263 else
00264 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
00265 fprintf(file, buffer);
00266 }
00267
00268 fprintf(file, "\n unset multiplot\n");
00269 fprintf(file, "set output 'Timing5.pdf\n");
00270 fprintf(file, "set terminal pdf\n");
00271
00272 fprintf(file, "set multiplot\n");
00273 fprintf(file, "set grid\n");
00274 fprintf(file, "set title \"Clients duration\"\n");
00275 fprintf(file, "set xlabel \"audio cycles\"\n");
00276 fprintf(file, "set ylabel \"usec\"\n");
00277 fprintf(file, "plot ");
00278 for (unsigned int i = 0; i < fMeasuredClient; i++) {
00279 if ((i + 1) == fMeasuredClient)
00280 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
00281 else
00282 sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
00283 fprintf(file, buffer);
00284 }
00285 fclose(file);
00286 }
00287 }
00288 }
00289
00290 bool JackEngineProfiling::CheckClient(const char* name, int cur_point)
00291 {
00292 for (int i = 0; i < MEASURED_CLIENTS; i++) {
00293 if (strcmp(fIntervalTable[i].fName, name) == 0) {
00294 fIntervalTable[i].fEndInterval = cur_point;
00295 return true;
00296 }
00297 }
00298 return false;
00299 }
00300
00301 void JackEngineProfiling::Profile(JackClientInterface** table,
00302 JackGraphManager* manager,
00303 jack_time_t period_usecs,
00304 jack_time_t cur_cycle_begin,
00305 jack_time_t prev_cycle_end)
00306 {
00307 fAudioCycle = (fAudioCycle + 1) % TIME_POINTS;
00308
00309
00310 fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs;
00311 fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin;
00312 fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
00313 fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;
00314
00315 for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
00316 JackClientInterface* client = table[i];
00317 JackClientTiming* timing = manager->GetClientTiming(i);
00318 if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {
00319
00320 if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) {
00321
00322 fIntervalTable[fMeasuredClient].fRefNum = i;
00323 strcpy(fIntervalTable[fMeasuredClient].fName, client->GetClientControl()->fName);
00324 fIntervalTable[fMeasuredClient].fBeginInterval = fAudioCycle;
00325 fIntervalTable[fMeasuredClient].fEndInterval = fAudioCycle;
00326 fMeasuredClient++;
00327 }
00328 fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i;
00329 fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt;
00330 fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt;
00331 fProfileTable[fAudioCycle].fClientTable[i].fFinishedAt = timing->fFinishedAt;
00332 fProfileTable[fAudioCycle].fClientTable[i].fStatus = timing->fStatus;
00333 }
00334 }
00335 }
00336
00337 JackTimingMeasure* JackEngineProfiling::GetCurMeasure()
00338 {
00339 return &fProfileTable[fAudioCycle];
00340 }
00341
00342 }