|
- /*
- Copyright (C) 2008 Grame & RTL
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- This program 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
-
- #include "JackEngineProfiling.h"
- #include "JackGraphManager.h"
- #include "JackClientControl.h"
- #include "JackClientInterface.h"
- #include "JackTime.h"
-
- namespace Jack
- {
-
- JackEngineProfiling::JackEngineProfiling():fAudioCycle(0)
- {
- jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
-
- // Force memory page in
- memset(fProfileTable, 0, sizeof(fProfileTable));
- }
-
- JackEngineProfiling::~JackEngineProfiling()
- {
- // Window monitoring
- int max_client = 0;
- char buffer[1024];
- char* nameTable[CLIENT_NUM];
- FILE* file = fopen("JackEngineProfiling.log", "w");
-
- jack_info("Write server and clients timing data...");
-
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
- } else {
-
- for (int i = 2; i < TIME_POINTS; i++) {
- bool header = true;
- bool printed = false;
- int count = 0;
- for (int j = REAL_REFNUM; j < CLIENT_NUM; j++) {
- if (fProfileTable[i].fClientTable[j].fRefNum > 0) {
- long d1 = long(fProfileTable[i - 1].fCurCycleBegin - fProfileTable[i - 2].fCurCycleBegin);
- long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
- if (d1 > 0 && fProfileTable[i].fClientTable[j].fStatus != NotTriggered) { // Valid cycle
- count++;
- nameTable[count] = fNameTable[fProfileTable[i].fClientTable[j].fRefNum];
-
- // driver delta and end cycle
- if (header) {
- fprintf(file, "%ld \t %ld \t", d1, d2);
- header = false;
- }
- long d5 = long(fProfileTable[i].fClientTable[j].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
- long d6 = long(fProfileTable[i].fClientTable[j].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
- long d7 = long(fProfileTable[i].fClientTable[j].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
-
- // ref, signal, start, end, scheduling, duration, status
- fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t",
- fProfileTable[i].fClientTable[j].fRefNum,
- ((d5 > 0) ? d5 : 0),
- ((d6 > 0) ? d6 : 0),
- ((d7 > 0) ? d7 : 0),
- ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0),
- ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0),
- fProfileTable[i].fClientTable[j].fStatus);
- printed = true;
- }
- }
- max_client = (count > max_client) ? count : max_client;
- }
- if (printed) {
- fprintf(file, "\n");
- } else if (fProfileTable[i].fAudioCycle > 0) { // Driver timing only
- long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
- long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
- if (d1 > 0) { // Valid cycle
- fprintf(file, "%ld \t %ld \n", d1, d2);
- }
- }
- }
- fclose(file);
- }
-
- // Driver period
- file = fopen("Timing1.plot", "w");
-
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open Timing1.log file");
- } else {
-
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Audio driver timing\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
-
- fprintf(file, "set output 'Timing1.pdf\n");
- fprintf(file, "set terminal pdf\n");
-
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Audio driver timing\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
-
- fclose(file);
- }
-
- // Driver end date
- file = fopen("Timing2.plot", "w");
-
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open Timing2.log file");
- } else {
-
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Driver end date\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
-
- fprintf(file, "set output 'Timing2.pdf\n");
- fprintf(file, "set terminal pdf\n");
-
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Driver end date\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
-
- fclose(file);
- }
-
- // Clients end date
- if (max_client > 0) {
- file = fopen("Timing3.plot", "w");
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open Timing3.log file");
- } else {
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients end date\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
-
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if (i == 0) {
- if ((i + 1) == max_client) {
- sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
- ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- } else {
- sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
- ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- }
- } else if ((i + 1) == max_client) { // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- } else {
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
- }
- fprintf(file, buffer);
- }
-
- fprintf(file, "\n unset multiplot\n");
- fprintf(file, "set output 'Timing3.pdf\n");
- fprintf(file, "set terminal pdf\n");
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients end date\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if (i == 0) {
- if ((i + 1) == max_client) {
- sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
- ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- } else {
- sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
- ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- }
- } else if ((i + 1) == max_client) { // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
- } else {
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
- }
- fprintf(file, buffer);
- }
- fclose(file);
- }
- }
-
- // Clients scheduling
- if (max_client > 0) {
- file = fopen("Timing4.plot", "w");
-
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open Timing4.log file");
- } else {
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients scheduling latency\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if ((i + 1) == max_client) // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
- else
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
- fprintf(file, buffer);
- }
-
- fprintf(file, "\n unset multiplot\n");
- fprintf(file, "set output 'Timing4.pdf\n");
- fprintf(file, "set terminal pdf\n");
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients scheduling latency\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if ((i + 1) == max_client) // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
- else
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
- fprintf(file, buffer);
- }
- fclose(file);
- }
- }
-
- // Clients duration
- if (max_client > 0) {
- file = fopen("Timing5.plot", "w");
-
- if (file == NULL) {
- jack_error("JackEngineProfiling::Save cannot open Timing5.log file");
- } else {
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients duration\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if ((i + 1) == max_client) // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
- else
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
- fprintf(file, buffer);
- }
-
- fprintf(file, "\n unset multiplot\n");
- fprintf(file, "set output 'Timing5.pdf\n");
- fprintf(file, "set terminal pdf\n");
-
- fprintf(file, "set multiplot\n");
- fprintf(file, "set grid\n");
- fprintf(file, "set title \"Clients duration\"\n");
- fprintf(file, "set xlabel \"audio cycles\"\n");
- fprintf(file, "set ylabel \"usec\"\n");
- fprintf(file, "plot ");
- for (int i = 0; i < max_client; i++) {
- if ((i + 1) == max_client) // Last client
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
- else
- sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
- fprintf(file, buffer);
- }
- fclose(file);
- }
- }
- }
-
- void JackEngineProfiling::Profile(JackClientInterface** table,
- JackGraphManager* manager,
- jack_time_t period_usecs,
- jack_time_t cur_cycle_begin,
- jack_time_t prev_cycle_end)
- {
- fAudioCycle = (fAudioCycle + 1) % TIME_POINTS;
-
- // Keeps cycle data
- fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs;
- fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin;
- fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
- fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;
-
- for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
- JackClientInterface* client = table[i];
- JackClientTiming* timing = manager->GetClientTiming(i);
- if (client && client->GetClientControl()->fActive) {
- strcpy(fNameTable[i], client->GetClientControl()->fName);
- fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i;
- fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt;
- fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt;
- fProfileTable[fAudioCycle].fClientTable[i].fFinishedAt = timing->fFinishedAt;
- fProfileTable[fAudioCycle].fClientTable[i].fStatus = timing->fStatus;
- }
- }
- }
-
- JackTimingMeasure* JackEngineProfiling::GetCurMeasure()
- {
- return &fProfileTable[fAudioCycle];
- }
-
- } // end of namespace
|