jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

230 lines
7.9KB

  1. /*
  2. Copyright (C) 2004-2006 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackEngineTiming.h"
  16. #include "JackClientInterface.h"
  17. #include "JackEngineControl.h"
  18. #include "JackClientControl.h"
  19. #include <math.h>
  20. #include <algorithm>
  21. #include <iostream>
  22. //#include <fstream>
  23. #include <assert.h>
  24. namespace Jack
  25. {
  26. inline jack_time_t MAX(jack_time_t a, jack_time_t b)
  27. {
  28. return (a < b) ? b : a;
  29. }
  30. JackEngineTiming::JackEngineTiming(JackClientInterface** table, JackGraphManager* manager, JackEngineControl* control)
  31. {
  32. fClientTable = table;
  33. fGraphManager = manager;
  34. fEngineControl = control;
  35. fLastTime = 0;
  36. fCurTime = 0;
  37. fProcessTime = 0;
  38. fLastProcessTime = 0;
  39. fSpareUsecs = 0;
  40. fMaxUsecs = 0;
  41. fAudioCycle = 0;
  42. }
  43. void JackEngineTiming::UpdateTiming(jack_time_t callback_usecs)
  44. {
  45. GetTimeMeasure(callback_usecs);
  46. CalcCPULoad();
  47. }
  48. void JackEngineTiming::CalcCPULoad()
  49. {
  50. jack_time_t lastCycleEnd = fLastProcessTime;
  51. for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
  52. JackClientInterface* client = fClientTable[i];
  53. JackClientTiming* timing = fGraphManager->GetClientTiming(i);
  54. if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) {
  55. lastCycleEnd = MAX(lastCycleEnd, timing->fFinishedAt);
  56. }
  57. }
  58. /* store the execution time for later averaging */
  59. fRollingClientUsecs[fRollingClientUsecsIndex++] = lastCycleEnd - fLastTime;
  60. if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) {
  61. fRollingClientUsecsIndex = 0;
  62. }
  63. /* every so often, recompute the current maximum use over the
  64. last JACK_ENGINE_ROLLING_COUNT client iterations.
  65. */
  66. if (++fRollingClientUsecsCnt % fRollingInterval == 0) {
  67. jack_time_t maxUsecs = 0;
  68. for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
  69. maxUsecs = MAX(fRollingClientUsecs[i], maxUsecs);
  70. }
  71. fMaxUsecs = MAX(fMaxUsecs, maxUsecs);
  72. fSpareUsecs = jack_time_t((maxUsecs < fEngineControl->fPeriodUsecs) ? fEngineControl->fPeriodUsecs - maxUsecs : 0);
  73. fEngineControl->fCPULoad
  74. = ((1.0f - (float(fSpareUsecs) / float(fEngineControl->fPeriodUsecs))) * 50.0f + (fEngineControl->fCPULoad * 0.5f));
  75. }
  76. }
  77. void JackEngineTiming::ResetRollingUsecs()
  78. {
  79. memset(fRollingClientUsecs, 0, sizeof(fRollingClientUsecs));
  80. fRollingClientUsecsIndex = 0;
  81. fRollingClientUsecsCnt = 0;
  82. fSpareUsecs = 0;
  83. fRollingInterval = (int)floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.0f) / fEngineControl->fPeriodUsecs);
  84. }
  85. void JackEngineTiming::GetTimeMeasure(jack_time_t callbackUsecs)
  86. {
  87. int pos = (++fAudioCycle) % TIME_POINTS;
  88. fLastTime = fCurTime;
  89. fCurTime = callbackUsecs;
  90. fLastProcessTime = fProcessTime;
  91. fProcessTime = GetMicroSeconds();
  92. if (fLastTime > 0) {
  93. fMeasure[pos].fEngineTime = fLastTime;
  94. fMeasure[pos].fAudioCycle = fAudioCycle;
  95. for (int i = 0; i < CLIENT_NUM; i++) {
  96. JackClientInterface* client = fClientTable[i];
  97. JackClientTiming* timing = fGraphManager->GetClientTiming(i);
  98. if (client && client->GetClientControl()->fActive) {
  99. fMeasure[pos].fClientTable[i].fRefNum = i;
  100. fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt;
  101. fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt;
  102. fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt;
  103. fMeasure[pos].fClientTable[i].fStatus = timing->fStatus;
  104. }
  105. }
  106. }
  107. }
  108. void JackEngineTiming::PrintState()
  109. {
  110. jack_time_t prevtime, time;
  111. prevtime = time = fMeasure[0].fEngineTime;
  112. int cycle, prevcycle = fMeasure[0].fAudioCycle;
  113. /*
  114. std::ofstream f("measure.txt");
  115. if (f.is_open()) {
  116. //std::cout << "---------------------------------------------" << std::endl;
  117. for (int i = 0; i < CLIENT_NUM; i++) { // client
  118. JackClientInterface* client = fClientTable[i];
  119. if (client && client->GetClientControl()->fActive) {
  120. // f << "Client : " << i << std::endl;
  121. long maxsignalledat = 0;
  122. long maxawakedat = 0;
  123. long maxfinisheddat = 0;
  124. bool max = false;
  125. prevtime = fMeasure[0].fEngineTime;
  126. prevcycle = fMeasure[0].fAudioCycle;
  127. // TODO
  128. for (int j = 0; j < TIME_POINTS; j++) { // measure
  129. time = fMeasure[j].fEngineTime;
  130. cycle = fMeasure[j].fAudioCycle;
  131. if (fMeasure[j].fClientTable[i].fRefNum > 0) {
  132. if (fMeasure[j].fClientTable[i].fStatus != Finished) {
  133. f << "error status " << '\t'
  134. << prevtime << '\t'
  135. << time << '\t'
  136. << fMeasure[j + 1].fEngineTime << '\t'
  137. << prevcycle << '\t'
  138. << cycle << '\t'
  139. << fMeasure[j].fClientTable[i].fSignaledAt << '\t'
  140. << fMeasure[j].fClientTable[i].fAwakeAt << '\t'
  141. << fMeasure[j].fClientTable[i].fFinishedAt
  142. << std::endl;
  143. }
  144. if (long(time - prevtime) > 0) {
  145. f << long(time - prevtime) << '\t'
  146. << fMeasure[j].fClientTable[i].fSignaledAt - time << '\t'
  147. << fMeasure[j].fClientTable[i].fAwakeAt - time << '\t'
  148. << fMeasure[j].fClientTable[i].fFinishedAt - time << '\t'
  149. << fMeasure[j].fClientTable[i].fStatus
  150. << std::endl;
  151. } else {
  152. f << "error time : " << j << " " << long(time - prevtime) << std::endl;
  153. }
  154. maxsignalledat = MAX(maxsignalledat, long(fMeasure[j].fClientTable[i].fSignaledAt - time));
  155. maxawakedat = MAX(maxawakedat, long(fMeasure[j].fClientTable[i].fAwakeAt - time));
  156. maxfinisheddat = MAX(maxfinisheddat, long(fMeasure[j].fClientTable[i].fFinishedAt - time));
  157. max = true;
  158. }
  159. prevtime = time;
  160. prevcycle = cycle;
  161. }
  162. f << std::endl;
  163. if (max) {
  164. f << "maxsignalledat: " << maxsignalledat
  165. << '\t' << "maxawakedat: " << maxawakedat
  166. << '\t' << "maxfinisheddat: " << maxfinisheddat
  167. << '\t' << std::endl;
  168. }
  169. }
  170. }
  171. f.close();
  172. }
  173. */
  174. }
  175. void JackEngineTiming::ClearTimeMeasures()
  176. {
  177. for (int i = 0; i < TIME_POINTS; i++) {
  178. for (int j = 0; j < CLIENT_NUM; j++) {
  179. fMeasure[i].fClientTable[j].fRefNum = 0;
  180. fMeasure[i].fClientTable[j].fSignaledAt = 0;
  181. fMeasure[i].fClientTable[j].fAwakeAt = 0;
  182. fMeasure[i].fClientTable[j].fFinishedAt = 0;
  183. }
  184. }
  185. fLastTime = fCurTime = 0;
  186. }
  187. } // end of namespace