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"
32 inline jack_time_t
MAX(jack_time_t a
, jack_time_t b
)
34 return (a
< b
) ? b
: a
;
37 JackEngineTiming::JackEngineTiming(JackClientInterface
** table
, JackGraphManager
* manager
, JackEngineControl
* control
)
40 fGraphManager
= manager
;
41 fEngineControl
= control
;
51 void JackEngineTiming::UpdateTiming(jack_time_t callback_usecs
)
53 GetTimeMeasure(callback_usecs
);
57 void JackEngineTiming::CalcCPULoad()
59 jack_time_t lastCycleEnd
= fLastProcessTime
;
61 for (int i
= REAL_REFNUM
; i
< CLIENT_NUM
; i
++) {
62 JackClientInterface
* client
= fClientTable
[i
];
63 JackClientTiming
* timing
= fGraphManager
->GetClientTiming(i
);
64 if (client
&& client
->GetClientControl()->fActive
&& timing
->fStatus
== Finished
) {
65 lastCycleEnd
= MAX(lastCycleEnd
, timing
->fFinishedAt
);
69 /* store the execution time for later averaging */
70 fRollingClientUsecs
[fRollingClientUsecsIndex
++] = lastCycleEnd
- fLastTime
;
72 if (fRollingClientUsecsIndex
>= JACK_ENGINE_ROLLING_COUNT
) {
73 fRollingClientUsecsIndex
= 0;
76 /* every so often, recompute the current maximum use over the
77 last JACK_ENGINE_ROLLING_COUNT client iterations.
80 if (++fRollingClientUsecsCnt
% fRollingInterval
== 0) {
82 jack_time_t maxUsecs
= 0;
83 for (int i
= 0; i
< JACK_ENGINE_ROLLING_COUNT
; i
++) {
84 maxUsecs
= MAX(fRollingClientUsecs
[i
], maxUsecs
);
87 fMaxUsecs
= MAX(fMaxUsecs
, maxUsecs
);
88 fSpareUsecs
= jack_time_t((maxUsecs
< fEngineControl
->fPeriodUsecs
) ? fEngineControl
->fPeriodUsecs
- maxUsecs
: 0);
89 fEngineControl
->fCPULoad
90 = ((1.0f
- (float(fSpareUsecs
) / float(fEngineControl
->fPeriodUsecs
))) * 50.0f
+ (fEngineControl
->fCPULoad
* 0.5f
));
94 void JackEngineTiming::ResetRollingUsecs()
96 memset(fRollingClientUsecs
, 0, sizeof(fRollingClientUsecs
));
97 fRollingClientUsecsIndex
= 0;
98 fRollingClientUsecsCnt
= 0;
100 fRollingInterval
= (int)floor((JACK_ENGINE_ROLLING_INTERVAL
* 1000.0f
) / fEngineControl
->fPeriodUsecs
);
103 void JackEngineTiming::GetTimeMeasure(jack_time_t callbackUsecs
)
105 int pos
= (++fAudioCycle
) % TIME_POINTS
;
107 fLastTime
= fCurTime
;
108 fCurTime
= callbackUsecs
;
110 fLastProcessTime
= fProcessTime
;
111 fProcessTime
= GetMicroSeconds();
114 fMeasure
[pos
].fEngineTime
= fLastTime
;
115 fMeasure
[pos
].fAudioCycle
= fAudioCycle
;
117 for (int i
= 0; i
< CLIENT_NUM
; i
++) {
118 JackClientInterface
* client
= fClientTable
[i
];
119 JackClientTiming
* timing
= fGraphManager
->GetClientTiming(i
);
120 if (client
&& client
->GetClientControl()->fActive
) {
121 fMeasure
[pos
].fClientTable
[i
].fRefNum
= i
;
122 fMeasure
[pos
].fClientTable
[i
].fSignaledAt
= timing
->fSignaledAt
;
123 fMeasure
[pos
].fClientTable
[i
].fAwakeAt
= timing
->fAwakeAt
;
124 fMeasure
[pos
].fClientTable
[i
].fFinishedAt
= timing
->fFinishedAt
;
125 fMeasure
[pos
].fClientTable
[i
].fStatus
= timing
->fStatus
;
131 void JackEngineTiming::PrintState()
133 jack_time_t prevtime
, time
;
134 prevtime
= time
= fMeasure
[0].fEngineTime
;
135 int cycle
, prevcycle
= fMeasure
[0].fAudioCycle
;
138 std::ofstream f("measure.txt");
142 //std::cout << "---------------------------------------------" << std::endl;
144 for (int i = 0; i < CLIENT_NUM; i++) { // client
145 JackClientInterface* client = fClientTable[i];
146 if (client && client->GetClientControl()->fActive) {
147 // f << "Client : " << i << std::endl;
148 long maxsignalledat = 0;
149 long maxawakedat = 0;
150 long maxfinisheddat = 0;
152 prevtime = fMeasure[0].fEngineTime;
153 prevcycle = fMeasure[0].fAudioCycle;
157 for (int j = 0; j < TIME_POINTS; j++) { // measure
158 time = fMeasure[j].fEngineTime;
159 cycle = fMeasure[j].fAudioCycle;
161 if (fMeasure[j].fClientTable[i].fRefNum > 0) {
163 if (fMeasure[j].fClientTable[i].fStatus != Finished) {
164 f << "error status " << '\t'
167 << fMeasure[j + 1].fEngineTime << '\t'
170 << fMeasure[j].fClientTable[i].fSignaledAt << '\t'
171 << fMeasure[j].fClientTable[i].fAwakeAt << '\t'
172 << fMeasure[j].fClientTable[i].fFinishedAt
176 if (long(time - prevtime) > 0) {
178 f << long(time - prevtime) << '\t'
179 << fMeasure[j].fClientTable[i].fSignaledAt - time << '\t'
180 << fMeasure[j].fClientTable[i].fAwakeAt - time << '\t'
181 << fMeasure[j].fClientTable[i].fFinishedAt - time << '\t'
182 << fMeasure[j].fClientTable[i].fStatus
185 f << "error time : " << j << " " << long(time - prevtime) << std::endl;
188 maxsignalledat = MAX(maxsignalledat, long(fMeasure[j].fClientTable[i].fSignaledAt - time));
189 maxawakedat = MAX(maxawakedat, long(fMeasure[j].fClientTable[i].fAwakeAt - time));
190 maxfinisheddat = MAX(maxfinisheddat, long(fMeasure[j].fClientTable[i].fFinishedAt - time));
200 f << "maxsignalledat: " << maxsignalledat
201 << '\t' << "maxawakedat: " << maxawakedat
202 << '\t' << "maxfinisheddat: " << maxfinisheddat
203 << '\t' << std::endl;
213 void JackEngineTiming::ClearTimeMeasures()
215 for (int i
= 0; i
< TIME_POINTS
; i
++) {
216 for (int j
= 0; j
< CLIENT_NUM
; j
++) {
217 fMeasure
[i
].fClientTable
[j
].fRefNum
= 0;
218 fMeasure
[i
].fClientTable
[j
].fSignaledAt
= 0;
219 fMeasure
[i
].fClientTable
[j
].fAwakeAt
= 0;
220 fMeasure
[i
].fClientTable
[j
].fFinishedAt
= 0;
223 fLastTime
= fCurTime
= 0;
227 } // end of namespace