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