20 #include "JackEngineProfiling.h"    21 #include "JackGraphManager.h"    22 #include "JackClientControl.h"    23 #include "JackEngineControl.h"    24 #include "JackClientInterface.h"    25 #include "JackGlobals.h"    34 JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0)
    36     jack_info(
"Engine profiling activated, beware %ld MBytes are needed to record profiling points...", 
sizeof(fProfileTable) / (1024 * 1024));
    39     memset(fProfileTable, 0, 
sizeof(fProfileTable));
    42 JackEngineProfiling::~JackEngineProfiling()
    44     std::ofstream fStream(
"JackEngineProfiling.log", std::ios_base::ate);
    45     jack_info(
"Write server and clients timing data...");
    47     if (!fStream.is_open()) {
    48         jack_error(
"JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
    52         for (
int i = 2; i < TIME_POINTS; i++) {
    55             long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
    56             long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
    58             if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
    62             fStream << d1 << 
"\t" << d2 << 
"\t";
    65             for (
unsigned int j = 0; j < fMeasuredClient; j++) {
    67                 int ref = fIntervalTable[j].fRefNum;
    70                 if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
    72                     long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
    73                     long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
    74                     long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
    76                      fStream << ref << 
"\t" ;
    77                      fStream << ((d5 > 0) ? d5 : 0) << 
"\t";
    78                      fStream << ((d6 > 0) ? d6 : 0) << 
"\t" ;
    79                      fStream << ((d7 > 0) ? d7 : 0) << 
"\t";
    80                      fStream << ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0) << 
"\t" ;
    81                      fStream << ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0) << 
"\t" ;
    82                      fStream << fProfileTable[i].fClientTable[ref].fStatus << 
"\t" ;;
    85                      fStream <<  
"\t  \t  \t  \t  \t  \t \t";
    95      std::ofstream fStream1(
"Timing1.plot", std::ios_base::ate);
    97     if (!fStream1.is_open()) {
    98         jack_error(
"JackEngineProfiling::Save cannot open Timing1.plot file");
   101         fStream1 << 
"set grid\n";
   102         fStream1 <<  
"set title \"Audio driver timing\"\n";
   103         fStream1 <<  
"set xlabel \"audio cycles\"\n";
   104         fStream1 <<  
"set ylabel \"usec\"\n";
   105         fStream1 <<  
"plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
   107         fStream1 <<  
"set output 'Timing1.svg\n";
   108         fStream1 <<  
"set terminal svg\n";
   110         fStream1 <<  
"set grid\n";
   111         fStream1 <<  
"set title \"Audio driver timing\"\n";
   112         fStream1 <<  
"set xlabel \"audio cycles\"\n";
   113         fStream1 <<  
"set ylabel \"usec\"\n";
   114         fStream1 <<  
"plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
   115         fStream1 <<  
"unset output\n";
   119     std::ofstream fStream2(
"Timing2.plot", std::ios_base::ate);
   121     if (!fStream2.is_open()) {
   122         jack_error(
"JackEngineProfiling::Save cannot open Timing2.plot file");
   125         fStream2 << 
"set grid\n";
   126         fStream2 <<  
"set title \"Driver end date\"\n";
   127         fStream2 <<  
"set xlabel \"audio cycles\"\n";
   128         fStream2 <<  
"set ylabel \"usec\"\n";
   129         fStream2 <<  
"plot  \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
   131         fStream2 <<  
"set output 'Timing2.svg\n";
   132         fStream2 <<  
"set terminal svg\n";
   134         fStream2 <<  
"set grid\n";
   135         fStream2 <<  
"set title \"Driver end date\"\n";
   136         fStream2 <<  
"set xlabel \"audio cycles\"\n";
   137         fStream2 <<  
"set ylabel \"usec\"\n";
   138         fStream2 <<  
"plot  \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
   139         fStream2 <<  
"unset output\n";
   143     if (fMeasuredClient > 0) {
   144         std::ofstream fStream3(
"Timing3.plot", std::ios_base::ate);
   146         if (!fStream3.is_open()) {
   147             jack_error(
"JackEngineProfiling::Save cannot open Timing3.plot file");
   150             fStream3 << 
"set multiplot\n";
   151             fStream3 << 
"set grid\n";
   152             fStream3 << 
"set title \"Clients end date\"\n";
   153             fStream3 << 
"set xlabel \"audio cycles\"\n";
   154             fStream3 << 
"set ylabel \"usec\"\n";
   156             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   158                     if (i + 1 == fMeasuredClient) { 
   159                         fStream3 << 
"\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using ";
   160                         fStream3 <<  ((i + 1) * 7) - 1;
   161                         fStream3 << 
" title \"" << fIntervalTable[i].fName << 
"\"with lines";
   163                         fStream3 << 
"\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using ";
   164                         fStream3 <<  ((i + 1) * 7) - 1;
   165                         fStream3 << 
" title \"" << fIntervalTable[i].fName << 
"\"with lines,";
   167                 } 
else if (i + 1 == fMeasuredClient) { 
   168                     fStream3 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   170                     fStream3 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   174             fStream3 << 
"\n unset multiplot\n";
   175             fStream3 << 
"set output 'Timing3.svg\n";
   176             fStream3 << 
"set terminal svg\n";
   178             fStream3 << 
"set multiplot\n";
   179             fStream3 << 
"set grid\n";
   180             fStream3 << 
"set title \"Clients end date\"\n";
   181             fStream3 << 
"set xlabel \"audio cycles\"\n";
   182             fStream3 << 
"set ylabel \"usec\"\n";
   184             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   186                     if ((i + 1) == fMeasuredClient) { 
   187                         fStream3 << 
"\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using ";
   188                         fStream3 <<  ((i + 1) * 7) - 1;
   189                         fStream3 << 
" title \"" << fIntervalTable[i].fName << 
"\"with lines";
   191                         fStream3 << 
"\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using ";
   192                         fStream3 <<  ((i + 1) * 7) - 1;
   193                         fStream3 << 
" title \"" << fIntervalTable[i].fName << 
"\"with lines,";
   195                 } 
else if ((i + 1) == fMeasuredClient) { 
   196                     fStream3 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   198                     fStream3 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   201             fStream3 << 
"\nunset multiplot\n";
   202             fStream3 << 
"unset output\n";
   207     if (fMeasuredClient > 0) {
   208         std::ofstream fStream4(
"Timing4.plot", std::ios_base::ate);
   210         if (!fStream4.is_open()) {
   211             jack_error(
"JackEngineProfiling::Save cannot open Timing4.plot file");
   214             fStream4 << 
"set multiplot\n";
   215             fStream4 << 
"set grid\n";
   216             fStream4 << 
"set title \"Clients scheduling latency\"\n";
   217             fStream4 << 
"set xlabel \"audio cycles\"\n";
   218             fStream4 << 
"set ylabel \"usec\"\n";
   220             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   221                 if ((i + 1) == fMeasuredClient) { 
   222                     fStream4 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7)  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   224                      fStream4 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7)  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   228             fStream4 << 
"\n unset multiplot\n";
   229             fStream4 << 
"set output 'Timing4.svg\n";
   230             fStream4 << 
"set terminal svg\n";
   232             fStream4 << 
"set multiplot\n";
   233             fStream4 << 
"set grid\n";
   234             fStream4 << 
"set title \"Clients scheduling latency\"\n";
   235             fStream4 << 
"set xlabel \"audio cycles\"\n";
   236             fStream4 << 
"set ylabel \"usec\"\n";
   238             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   239                 if ((i + 1) == fMeasuredClient) { 
   240                     fStream4 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7)  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   242                      fStream4 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7)  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   245             fStream4 << 
"\nunset multiplot\n";
   246             fStream4 << 
"unset output\n";
   251     if (fMeasuredClient > 0) {
   252         std::ofstream fStream5(
"Timing5.plot", std::ios_base::ate);
   254         if (!fStream5.is_open()) {
   255             jack_error(
"JackEngineProfiling::Save cannot open Timing5.plot file");
   258             fStream5 << 
"set multiplot\n";
   259             fStream5 << 
"set grid\n";
   260             fStream5 << 
"set title \"Clients duration\"\n";
   261             fStream5 << 
"set xlabel \"audio cycles\"\n";
   262             fStream5 << 
"set ylabel \"usec\"\n";
   264             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   265                 if ((i + 1) == fMeasuredClient) { 
   266                     fStream5 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   268                     fStream5 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   272             fStream5 << 
"\n unset multiplot\n";
   273             fStream5 << 
"set output 'Timing5.svg\n";
   274             fStream5 << 
"set terminal svg\n";
   276             fStream5 << 
"set multiplot\n";
   277             fStream5 << 
"set grid\n";
   278             fStream5 << 
"set title \"Clients duration\"\n";
   279             fStream5 << 
"set xlabel \"audio cycles\"\n";
   280             fStream5 << 
"set ylabel \"usec\"\n";
   282             for (
unsigned int i = 0; i < fMeasuredClient; i++) {
   283                 if ((i + 1) == fMeasuredClient) {
   284                     fStream5 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines";
   286                     fStream5 << 
"\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1  << 
" title \"" << fIntervalTable[i].fName << 
"\" with lines,";
   289             fStream5 << 
"\nunset multiplot\n";
   290             fStream5 << 
"unset output\n";
   294     std::ofstream fStream6(
"Timings.html", std::ios_base::ate);
   295     if (!fStream6.is_open()) {
   296         jack_error(
"JackEngineProfiling::Save cannot open Timings.html file");
   298         fStream6 << 
"<?xml version='1.0' encoding='utf-8'?>\n";
   299         fStream6 << 
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n";
   300         fStream6 << 
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
   301         fStream6 << 
"<html xmlns='http://www.w3.org/1999/xhtml' lang='en'>\n";
   302         fStream6 << 
"  <head>\n";
   303         fStream6 << 
"    <title>JACK engine profiling</title>\n";
   304         fStream6 << 
"    <!-- assuming that images are 600px wide -->\n";
   305         fStream6 << 
"    <style media='all' type='text/css'>\n";
   306         fStream6 << 
"    .center { margin-left:auto ; margin-right: auto; width: 650px; height: 550px }\n";
   307         fStream6 << 
"    </style>\n";
   308         fStream6 << 
"  </head>\n";
   309         fStream6 << 
"  <body>\n";
   310         fStream6 << 
"    <h2 style='text-align:center'>JACK engine profiling</h2>\n";
   311         fStream6 << 
"    <div class='center'><object class='center' type='image/svg+xml' data='Timing1.svg'>Timing1</object></div>";
   312         fStream6 << 
"    <div class='center'><object class='center' type='image/svg+xml' data='Timing2.svg'>Timing2</object></div>";
   313         fStream6 << 
"    <div class='center'><object class='center' type='image/svg+xml' data='Timing3.svg'>Timing3</object></div>";
   314         fStream6 << 
"    <div class='center'><object class='center' type='image/svg+xml' data='Timing4.svg'>Timing4</object></div>";
   315         fStream6 << 
"    <div class='center'><object class='center' type='image/svg+xml' data='Timing5.svg'>Timing5</object></div>";
   316         fStream6 << 
"  </body>\n";
   317         fStream6 << 
"</html>\n";
   320     std::ofstream fStream7(
"generate_timings", std::ios_base::ate);
   321     if (!fStream7.is_open()) {
   322         jack_error(
"JackEngineProfiling::Save cannot open generate_timings file");
   324         fStream7 << 
"gnuplot -persist Timing1.plot \n";
   325         fStream7 << 
"gnuplot -persist Timing2.plot\n";
   326         fStream7 << 
"gnuplot -persist Timing3.plot\n";
   327         fStream7 << 
"gnuplot -persist Timing4.plot\n";
   328         fStream7 << 
"gnuplot -persist Timing5.plot\n";
   332 bool JackEngineProfiling::CheckClient(
const char* name, 
int cur_point)
   334     for (
int i = 0; i < MEASURED_CLIENTS; i++) {
   335        if (strcmp(fIntervalTable[i].fName, name) == 0) {
   336             fIntervalTable[i].fEndInterval = cur_point;
   343 void JackEngineProfiling::Profile(JackClientInterface** table,
   344                                    JackGraphManager* manager,
   345                                    jack_time_t period_usecs,
   346                                    jack_time_t cur_cycle_begin,
   347                                    jack_time_t prev_cycle_end)
   349     fAudioCycle = (fAudioCycle + 1) % TIME_POINTS;
   352     fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs;
   353     fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin;
   354     fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
   355     fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;
   357     for (
int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
   358         JackClientInterface* client = table[i];
   359         JackClientTiming* timing = manager->GetClientTiming(i);
   360         if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {
   362             if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) {
   364                 fIntervalTable[fMeasuredClient].fRefNum = i;
   365                 strcpy(fIntervalTable[fMeasuredClient].fName, client->GetClientControl()->fName);
   366                 fIntervalTable[fMeasuredClient].fBeginInterval = fAudioCycle;
   367                 fIntervalTable[fMeasuredClient].fEndInterval = fAudioCycle;
   370             fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i;
   371             fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt;
   372             fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt;
   373             fProfileTable[fAudioCycle].fClientTable[i].fFinishedAt = timing->fFinishedAt;
   374             fProfileTable[fAudioCycle].fClientTable[i].fStatus = timing->fStatus;
   379 JackTimingMeasure* JackEngineProfiling::GetCurMeasure()
   381     return &fProfileTable[fAudioCycle];
 
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)