| 
							- /*
 - 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),fMeasuredClient(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()
 - {
 -     FILE* file = fopen("JackEngineProfiling.log", "w");
 -     char buffer[1024];
 -     
 -     jack_info("Write server and clients timing data...");
 - 
 -     if (file == NULL) {
 -         jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
 -     } else {
 -     
 -         // For each measured point
 -         for (int i = 2; i < TIME_POINTS; i++) {
 -             
 -             // Driver timing values
 -             long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
 -             long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
 -             
 -             if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
 -                 continue; // Skip non valid cycles
 -                 
 -             // Print driver delta and end cycle
 -             fprintf(file, "%ld \t %ld \t", d1, d2);
 -              
 -             // For each measured client
 -             for (unsigned int j = 0; j < fMeasuredClient; j++) { 
 -             
 -                 int ref = fIntervalTable[j].fRefNum;
 -             
 -                 // Is valid client cycle 
 -                  if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
 -              
 -                     long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
 -                     long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
 -                     long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
 -              
 -                     // Print ref, signal, start, end, scheduling, duration, status
 -                     fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t", 
 -                             ref,
 -                             ((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[ref].fStatus);
 -                 } else { // Print tabs
 -                      fprintf(file, "\t  \t  \t  \t  \t  \t \t");
 -                 }
 -             }
 -             
 -             // Terminate line
 -             fprintf(file, "\n");
 -         }
 -     }
 -     
 -     // 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 (fMeasuredClient > 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if (i == 0) {
 -                     if (i + 1 == fMeasuredClient) { // Last client
 -                         sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", 
 -                         ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                     } else {
 -                         sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", 
 -                         ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                     }
 -                 } else if (i + 1 == fMeasuredClient) { // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                 } else {
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
 -                 }
 -                 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if (i == 0) {
 -                     if ((i + 1) == fMeasuredClient) { // Last client
 -                         sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", 
 -                         ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                     } else {
 -                         sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", 
 -                         ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                     }
 -                 } else if ((i + 1) == fMeasuredClient) { // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName);
 -                 } else {
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName);
 -                 }
 -                 fprintf(file, buffer);
 -             }
 -              
 -             fclose(file);
 -         }
 -     }
 - 
 -     // Clients scheduling
 -     if (fMeasuredClient > 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if ((i + 1) == fMeasuredClient) // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
 -                 else
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
 -                 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if ((i + 1) == fMeasuredClient) // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName);
 -                 else
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName);
 -                 fprintf(file, buffer);
 -             }
 -             fclose(file);
 -         }
 -     }
 -     
 -      // Clients duration
 -     if (fMeasuredClient > 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if ((i + 1) == fMeasuredClient) // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
 -                 else
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
 -                 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 (unsigned int i = 0; i < fMeasuredClient; i++) {
 -                 if ((i + 1) == fMeasuredClient) // Last client
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
 -                 else
 -                     sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName);
 -                 fprintf(file, buffer);
 -             }
 -             fclose(file);
 -         }
 -     }
 - }
 - 
 - bool JackEngineProfiling::CheckClient(const char* name, int cur_point)
 - {
 -     for (int i = 0; i < MEASURED_CLIENTS; i++) {
 -        if (strcmp(fIntervalTable[i].fName, name) == 0) {
 -             fIntervalTable[i].fEndInterval = cur_point;
 -             return true;
 -         }
 -     }
 -     return false;
 - }
 - 
 - 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 && client->GetClientControl()->fCallback[kRealTimeCallback]) {
 -            
 -             if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) {
 -                 // Keep new measured client
 -                 fIntervalTable[fMeasuredClient].fRefNum = i;
 -                 strcpy(fIntervalTable[fMeasuredClient].fName, client->GetClientControl()->fName);
 -                 fIntervalTable[fMeasuredClient].fBeginInterval = fAudioCycle;
 -                 fIntervalTable[fMeasuredClient].fEndInterval = fAudioCycle;
 -                 fMeasuredClient++;
 -             }
 -             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
 
 
  |