JackEngineTiming.cpp

00001 /*
00002 Copyright (C) 2004-2006 Grame  
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #include "JackEngineTiming.h"
00021 #include "JackClientInterface.h"
00022 #include "JackEngineControl.h"
00023 #include "JackClientControl.h"
00024 #include <math.h>
00025 #include <algorithm>
00026 #include <iostream> 
00027 //#include <fstream>
00028 #include <assert.h>
00029 
00030 namespace Jack
00031 {
00032 
00033 inline jack_time_t MAX(jack_time_t a, jack_time_t b)
00034 {
00035     return (a < b) ? b : a;
00036 }
00037 
00038 JackEngineTiming::JackEngineTiming(JackClientInterface** table, JackGraphManager* manager, JackEngineControl* control)
00039 {
00040     fClientTable = table;
00041     fGraphManager = manager;
00042     fEngineControl = control;
00043     fLastTime = 0;
00044     fCurTime = 0;
00045     fProcessTime = 0;
00046     fLastProcessTime = 0;
00047     fSpareUsecs = 0;
00048     fMaxUsecs = 0;
00049     fAudioCycle = 0;
00050 }
00051 
00052 void JackEngineTiming::UpdateTiming(jack_time_t callback_usecs)
00053 {
00054     GetTimeMeasure(callback_usecs);
00055     CalcCPULoad();
00056 }
00057 
00058 void JackEngineTiming::CalcCPULoad()
00059 {
00060     jack_time_t lastCycleEnd = fLastProcessTime;
00061 
00062     for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
00063         JackClientInterface* client = fClientTable[i];
00064                 JackClientTiming* timing = fGraphManager->GetClientTiming(i);
00065                 if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) {
00066             lastCycleEnd = MAX(lastCycleEnd, timing->fFinishedAt);
00067         }
00068     }
00069 
00070     /* store the execution time for later averaging */
00071     fRollingClientUsecs[fRollingClientUsecsIndex++] = lastCycleEnd - fLastTime;
00072 
00073     if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) {
00074         fRollingClientUsecsIndex = 0;
00075     }
00076 
00077     /* every so often, recompute the current maximum use over the
00078        last JACK_ENGINE_ROLLING_COUNT client iterations.
00079     */
00080 
00081     if (++fRollingClientUsecsCnt % fRollingInterval == 0) {
00082 
00083         jack_time_t maxUsecs = 0;
00084         for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
00085             maxUsecs = MAX(fRollingClientUsecs[i], maxUsecs);
00086         }
00087 
00088         fMaxUsecs = MAX(fMaxUsecs, maxUsecs);
00089         fSpareUsecs = jack_time_t((maxUsecs < fEngineControl->fPeriodUsecs) ? fEngineControl->fPeriodUsecs - maxUsecs : 0);
00090         fEngineControl->fCPULoad
00091         = ((1.0f - (float(fSpareUsecs) / float(fEngineControl->fPeriodUsecs))) * 50.0f + (fEngineControl->fCPULoad * 0.5f));
00092     }
00093 }
00094 
00095 void JackEngineTiming::ResetRollingUsecs()
00096 {
00097     memset(fRollingClientUsecs, 0, sizeof(fRollingClientUsecs));
00098     fRollingClientUsecsIndex = 0;
00099     fRollingClientUsecsCnt = 0;
00100     fSpareUsecs = 0;
00101     fRollingInterval = (int)floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.0f) / fEngineControl->fPeriodUsecs);
00102 }
00103 
00104 void JackEngineTiming::GetTimeMeasure(jack_time_t callbackUsecs)
00105 {
00106     int pos = (++fAudioCycle) % TIME_POINTS;
00107 
00108     fLastTime = fCurTime;
00109     fCurTime = callbackUsecs;
00110 
00111     fLastProcessTime = fProcessTime;
00112     fProcessTime = GetMicroSeconds();
00113 
00114     if (fLastTime > 0) {
00115         fMeasure[pos].fEngineTime = fLastTime;
00116         fMeasure[pos].fAudioCycle = fAudioCycle;
00117 
00118         for (int i = 0; i < CLIENT_NUM; i++) {
00119             JackClientInterface* client = fClientTable[i];
00120                         JackClientTiming* timing = fGraphManager->GetClientTiming(i);
00121             if (client && client->GetClientControl()->fActive) {
00122                             fMeasure[pos].fClientTable[i].fRefNum = i;
00123                 fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt;
00124                 fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt;
00125                 fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt;
00126                 fMeasure[pos].fClientTable[i].fStatus = timing->fStatus;
00127             }
00128         }
00129     }
00130 }
00131 
00132 void JackEngineTiming::PrintState()
00133 {
00134     jack_time_t prevtime, time;
00135     prevtime = time = fMeasure[0].fEngineTime;
00136     int cycle, prevcycle = fMeasure[0].fAudioCycle;
00137     /*
00138 
00139        std::ofstream f("measure.txt");
00140 
00141        if (f.is_open()) {
00142 
00143            //std::cout << "---------------------------------------------" << std::endl;
00144 
00145            for (int i = 0; i < CLIENT_NUM; i++) { // client
00146                JackClientInterface* client = fClientTable[i];
00147                 if (client && client->GetClientControl()->fActive) {
00148                    // f << "Client : " << i << std::endl;
00149                    long maxsignalledat = 0;
00150                    long maxawakedat = 0;
00151                    long maxfinisheddat = 0;
00152                    bool max = false;
00153                    prevtime = fMeasure[0].fEngineTime;
00154                    prevcycle = fMeasure[0].fAudioCycle;
00155 
00156                         // TODO
00157                         
00158                    for (int j = 0; j < TIME_POINTS; j++) { // measure
00159                        time = fMeasure[j].fEngineTime;
00160                        cycle = fMeasure[j].fAudioCycle;
00161 
00162                        if (fMeasure[j].fClientTable[i].fRefNum > 0) {
00163 
00164                            if (fMeasure[j].fClientTable[i].fStatus != Finished) {
00165                                f << "error status " << '\t'
00166                                << prevtime << '\t'
00167                                << time << '\t'
00168                                << fMeasure[j + 1].fEngineTime << '\t'
00169                                << prevcycle << '\t'
00170                                << cycle << '\t'
00171                                << fMeasure[j].fClientTable[i].fSignaledAt << '\t'
00172                                << fMeasure[j].fClientTable[i].fAwakeAt << '\t'
00173                                << fMeasure[j].fClientTable[i].fFinishedAt
00174                                << std::endl;
00175                            }
00176 
00177                            if (long(time - prevtime) > 0) {
00178 
00179                                f << long(time - prevtime) << '\t'
00180                                << fMeasure[j].fClientTable[i].fSignaledAt - time << '\t'
00181                                << fMeasure[j].fClientTable[i].fAwakeAt - time << '\t'
00182                                << fMeasure[j].fClientTable[i].fFinishedAt - time << '\t'
00183                                << fMeasure[j].fClientTable[i].fStatus
00184                                << std::endl;
00185                            } else {
00186                                f << "error time : " << j << " " << long(time - prevtime) << std::endl;
00187                            }
00188 
00189                            maxsignalledat = MAX(maxsignalledat, long(fMeasure[j].fClientTable[i].fSignaledAt - time));
00190                            maxawakedat = MAX(maxawakedat, long(fMeasure[j].fClientTable[i].fAwakeAt - time));
00191                            maxfinisheddat = MAX(maxfinisheddat, long(fMeasure[j].fClientTable[i].fFinishedAt - time));
00192                            max = true;
00193                        }
00194                        prevtime = time;
00195                        prevcycle = cycle;
00196                    }
00197                         
00198 
00199                    f << std::endl;
00200                    if (max) {
00201                        f << "maxsignalledat: " << maxsignalledat
00202                        << '\t' << "maxawakedat: " << maxawakedat
00203                        << '\t' << "maxfinisheddat: " << maxfinisheddat
00204                        << '\t' << std::endl;
00205                    }
00206                }
00207            }
00208 
00209            f.close();
00210        }
00211     */
00212 }
00213 
00214 void JackEngineTiming::ClearTimeMeasures()
00215 {
00216     for (int i = 0; i < TIME_POINTS; i++) {
00217         for (int j = 0; j < CLIENT_NUM; j++) {
00218             fMeasure[i].fClientTable[j].fRefNum = 0;
00219             fMeasure[i].fClientTable[j].fSignaledAt = 0;
00220             fMeasure[i].fClientTable[j].fAwakeAt = 0;
00221             fMeasure[i].fClientTable[j].fFinishedAt = 0;
00222         }
00223     }
00224     fLastTime = fCurTime = 0;
00225 }
00226 
00227 
00228 } // end of namespace
00229 

Generated on Wed Jan 10 11:42:45 2007 for Jackdmp by  doxygen 1.4.5