2 Copyright (C) 2004-2006 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackEngineTiming.h"
21 #include "JackClientInterface.h"
22 #include "JackEngineControl.h"
23 #include "JackClientControl.h"
33 inline jack_time_t
MAX(jack_time_t a
, jack_time_t b
)
35 return (a
< b
) ? b
: a
;
38 JackEngineTiming::JackEngineTiming(JackClientInterface
** table
, JackGraphManager
* manager
, JackEngineControl
* control
)
41 fGraphManager
= manager
;
42 fEngineControl
= control
;
52 void JackEngineTiming::UpdateTiming(jack_time_t callback_usecs
)
54 GetTimeMeasure(callback_usecs
);
58 void JackEngineTiming::CalcCPULoad()
60 jack_time_t lastCycleEnd
= fLastProcessTime
;
62 for (int i
= REAL_REFNUM
; i
< CLIENT_NUM
; i
++) {
63 JackClientInterface
* client
= fClientTable
[i
];
64 JackClientTiming
* timing
= fGraphManager
->GetClientTiming(i
);
65 if (client
&& client
->GetClientControl()->fActive
&& timing
->fStatus
== Finished
) {
66 lastCycleEnd
= MAX(lastCycleEnd
, timing
->fFinishedAt
);
70 /* store the execution time for later averaging */
71 fRollingClientUsecs
[fRollingClientUsecsIndex
++] = lastCycleEnd
- fLastTime
;
73 if (fRollingClientUsecsIndex
>= JACK_ENGINE_ROLLING_COUNT
) {
74 fRollingClientUsecsIndex
= 0;
77 /* every so often, recompute the current maximum use over the
78 last JACK_ENGINE_ROLLING_COUNT client iterations.
81 if (++fRollingClientUsecsCnt
% fRollingInterval
== 0) {
83 jack_time_t maxUsecs
= 0;
84 for (int i
= 0; i
< JACK_ENGINE_ROLLING_COUNT
; i
++) {
85 maxUsecs
= MAX(fRollingClientUsecs
[i
], maxUsecs
);
88 fMaxUsecs
= MAX(fMaxUsecs
, maxUsecs
);
89 fSpareUsecs
= jack_time_t((maxUsecs
< fEngineControl
->fPeriodUsecs
) ? fEngineControl
->fPeriodUsecs
- maxUsecs
: 0);
90 fEngineControl
->fCPULoad
91 = ((1.0f
- (float(fSpareUsecs
) / float(fEngineControl
->fPeriodUsecs
))) * 50.0f
+ (fEngineControl
->fCPULoad
* 0.5f
));
95 void JackEngineTiming::ResetRollingUsecs()
97 memset(fRollingClientUsecs
, 0, sizeof(fRollingClientUsecs
));
98 fRollingClientUsecsIndex
= 0;
99 fRollingClientUsecsCnt
= 0;
101 fRollingInterval
= (int)floor((JACK_ENGINE_ROLLING_INTERVAL
* 1000.0f
) / fEngineControl
->fPeriodUsecs
);
104 void JackEngineTiming::GetTimeMeasure(jack_time_t callbackUsecs
)
106 int pos
= (++fAudioCycle
) % TIME_POINTS
;
108 fLastTime
= fCurTime
;
109 fCurTime
= callbackUsecs
;
111 fLastProcessTime
= fProcessTime
;
112 fProcessTime
= GetMicroSeconds();
115 fMeasure
[pos
].fEngineTime
= fLastTime
;
116 fMeasure
[pos
].fAudioCycle
= fAudioCycle
;
118 for (int i
= 0; i
< CLIENT_NUM
; i
++) {
119 JackClientInterface
* client
= fClientTable
[i
];
120 JackClientTiming
* timing
= fGraphManager
->GetClientTiming(i
);
121 if (client
&& client
->GetClientControl()->fActive
) {
122 fMeasure
[pos
].fClientTable
[i
].fRefNum
= i
;
123 fMeasure
[pos
].fClientTable
[i
].fSignaledAt
= timing
->fSignaledAt
;
124 fMeasure
[pos
].fClientTable
[i
].fAwakeAt
= timing
->fAwakeAt
;
125 fMeasure
[pos
].fClientTable
[i
].fFinishedAt
= timing
->fFinishedAt
;
126 fMeasure
[pos
].fClientTable
[i
].fStatus
= timing
->fStatus
;
132 void JackEngineTiming::PrintState()
134 jack_time_t prevtime
, time
;
135 prevtime
= time
= fMeasure
[0].fEngineTime
;
136 int cycle
, prevcycle
= fMeasure
[0].fAudioCycle
;
139 std::ofstream f("measure.txt");
143 //std::cout << "---------------------------------------------" << std::endl;
145 for (int i = 0; i < CLIENT_NUM; i++) { // client
146 JackClientInterface* client = fClientTable[i];
147 if (client && client->GetClientControl()->fActive) {
148 // f << "Client : " << i << std::endl;
149 long maxsignalledat = 0;
150 long maxawakedat = 0;
151 long maxfinisheddat = 0;
153 prevtime = fMeasure[0].fEngineTime;
154 prevcycle = fMeasure[0].fAudioCycle;
158 for (int j = 0; j < TIME_POINTS; j++) { // measure
159 time = fMeasure[j].fEngineTime;
160 cycle = fMeasure[j].fAudioCycle;
162 if (fMeasure[j].fClientTable[i].fRefNum > 0) {
164 if (fMeasure[j].fClientTable[i].fStatus != Finished) {
165 f << "error status " << '\t'
168 << fMeasure[j + 1].fEngineTime << '\t'
171 << fMeasure[j].fClientTable[i].fSignaledAt << '\t'
172 << fMeasure[j].fClientTable[i].fAwakeAt << '\t'
173 << fMeasure[j].fClientTable[i].fFinishedAt
177 if (long(time - prevtime) > 0) {
179 f << long(time - prevtime) << '\t'
180 << fMeasure[j].fClientTable[i].fSignaledAt - time << '\t'
181 << fMeasure[j].fClientTable[i].fAwakeAt - time << '\t'
182 << fMeasure[j].fClientTable[i].fFinishedAt - time << '\t'
183 << fMeasure[j].fClientTable[i].fStatus
186 f << "error time : " << j << " " << long(time - prevtime) << std::endl;
189 maxsignalledat = MAX(maxsignalledat, long(fMeasure[j].fClientTable[i].fSignaledAt - time));
190 maxawakedat = MAX(maxawakedat, long(fMeasure[j].fClientTable[i].fAwakeAt - time));
191 maxfinisheddat = MAX(maxfinisheddat, long(fMeasure[j].fClientTable[i].fFinishedAt - time));
201 f << "maxsignalledat: " << maxsignalledat
202 << '\t' << "maxawakedat: " << maxawakedat
203 << '\t' << "maxfinisheddat: " << maxfinisheddat
204 << '\t' << std::endl;
214 void JackEngineTiming::ClearTimeMeasures()
216 for (int i
= 0; i
< TIME_POINTS
; i
++) {
217 for (int j
= 0; j
< CLIENT_NUM
; j
++) {
218 fMeasure
[i
].fClientTable
[j
].fRefNum
= 0;
219 fMeasure
[i
].fClientTable
[j
].fSignaledAt
= 0;
220 fMeasure
[i
].fClientTable
[j
].fAwakeAt
= 0;
221 fMeasure
[i
].fClientTable
[j
].fFinishedAt
= 0;
224 fLastTime
= fCurTime
= 0;
228 } // end of namespace