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.

229 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 <assert.h>
  23. namespace Jack
  24. {
  25. inline jack_time_t MAX(jack_time_t a, jack_time_t b)
  26. {
  27. return (a < b) ? b : a;
  28. }
  29. JackEngineTiming::JackEngineTiming(JackClientInterface** table, JackGraphManager* manager, JackEngineControl* control)
  30. {
  31. fClientTable = table;
  32. fGraphManager = manager;
  33. fEngineControl = control;
  34. fLastTime = 0;
  35. fCurTime = 0;
  36. fProcessTime = 0;
  37. fLastProcessTime = 0;
  38. fSpareUsecs = 0;
  39. fMaxUsecs = 0;
  40. fAudioCycle = 0;
  41. }
  42. void JackEngineTiming::UpdateTiming(jack_time_t callback_usecs)
  43. {
  44. GetTimeMeasure(callback_usecs);
  45. CalcCPULoad();
  46. }
  47. void JackEngineTiming::CalcCPULoad()
  48. {
  49. jack_time_t lastCycleEnd = fLastProcessTime;
  50. for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
  51. JackClientInterface* client = fClientTable[i];
  52. JackClientTiming* timing = fGraphManager->GetClientTiming(i);
  53. if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) {
  54. lastCycleEnd = MAX(lastCycleEnd, timing->fFinishedAt);
  55. }
  56. }
  57. /* store the execution time for later averaging */
  58. fRollingClientUsecs[fRollingClientUsecsIndex++] = lastCycleEnd - fLastTime;
  59. if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT) {
  60. fRollingClientUsecsIndex = 0;
  61. }
  62. /* every so often, recompute the current maximum use over the
  63. last JACK_ENGINE_ROLLING_COUNT client iterations.
  64. */
  65. if (++fRollingClientUsecsCnt % fRollingInterval == 0) {
  66. jack_time_t maxUsecs = 0;
  67. for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
  68. maxUsecs = MAX(fRollingClientUsecs[i], maxUsecs);
  69. }
  70. fMaxUsecs = MAX(fMaxUsecs, maxUsecs);
  71. fSpareUsecs = jack_time_t((maxUsecs < fEngineControl->fPeriodUsecs) ? fEngineControl->fPeriodUsecs - maxUsecs : 0);
  72. fEngineControl->fCPULoad
  73. = ((1.0f - (float(fSpareUsecs) / float(fEngineControl->fPeriodUsecs))) * 50.0f + (fEngineControl->fCPULoad * 0.5f));
  74. }
  75. }
  76. void JackEngineTiming::ResetRollingUsecs()
  77. {
  78. memset(fRollingClientUsecs, 0, sizeof(fRollingClientUsecs));
  79. fRollingClientUsecsIndex = 0;
  80. fRollingClientUsecsCnt = 0;
  81. fSpareUsecs = 0;
  82. fRollingInterval = (int)floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.0f) / fEngineControl->fPeriodUsecs);
  83. }
  84. void JackEngineTiming::GetTimeMeasure(jack_time_t callbackUsecs)
  85. {
  86. int pos = (++fAudioCycle) % TIME_POINTS;
  87. fLastTime = fCurTime;
  88. fCurTime = callbackUsecs;
  89. fLastProcessTime = fProcessTime;
  90. fProcessTime = GetMicroSeconds();
  91. if (fLastTime > 0) {
  92. fMeasure[pos].fEngineTime = fLastTime;
  93. fMeasure[pos].fAudioCycle = fAudioCycle;
  94. for (int i = 0; i < CLIENT_NUM; i++) {
  95. JackClientInterface* client = fClientTable[i];
  96. JackClientTiming* timing = fGraphManager->GetClientTiming(i);
  97. if (client && client->GetClientControl()->fActive) {
  98. fMeasure[pos].fClientTable[i].fRefNum = i;
  99. fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt;
  100. fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt;
  101. fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt;
  102. fMeasure[pos].fClientTable[i].fStatus = timing->fStatus;
  103. }
  104. }
  105. }
  106. }
  107. void JackEngineTiming::PrintState()
  108. {
  109. jack_time_t prevtime, time;
  110. prevtime = time = fMeasure[0].fEngineTime;
  111. int cycle, prevcycle = fMeasure[0].fAudioCycle;
  112. /*
  113. std::ofstream f("measure.txt");
  114. if (f.is_open()) {
  115. //std::cout << "---------------------------------------------" << std::endl;
  116. for (int i = 0; i < CLIENT_NUM; i++) { // client
  117. JackClientInterface* client = fClientTable[i];
  118. if (client && client->GetClientControl()->fActive) {
  119. // f << "Client : " << i << std::endl;
  120. long maxsignalledat = 0;
  121. long maxawakedat = 0;
  122. long maxfinisheddat = 0;
  123. bool max = false;
  124. prevtime = fMeasure[0].fEngineTime;
  125. prevcycle = fMeasure[0].fAudioCycle;
  126. // TODO
  127. for (int j = 0; j < TIME_POINTS; j++) { // measure
  128. time = fMeasure[j].fEngineTime;
  129. cycle = fMeasure[j].fAudioCycle;
  130. if (fMeasure[j].fClientTable[i].fRefNum > 0) {
  131. if (fMeasure[j].fClientTable[i].fStatus != Finished) {
  132. f << "error status " << '\t'
  133. << prevtime << '\t'
  134. << time << '\t'
  135. << fMeasure[j + 1].fEngineTime << '\t'
  136. << prevcycle << '\t'
  137. << cycle << '\t'
  138. << fMeasure[j].fClientTable[i].fSignaledAt << '\t'
  139. << fMeasure[j].fClientTable[i].fAwakeAt << '\t'
  140. << fMeasure[j].fClientTable[i].fFinishedAt
  141. << std::endl;
  142. }
  143. if (long(time - prevtime) > 0) {
  144. f << long(time - prevtime) << '\t'
  145. << fMeasure[j].fClientTable[i].fSignaledAt - time << '\t'
  146. << fMeasure[j].fClientTable[i].fAwakeAt - time << '\t'
  147. << fMeasure[j].fClientTable[i].fFinishedAt - time << '\t'
  148. << fMeasure[j].fClientTable[i].fStatus
  149. << std::endl;
  150. } else {
  151. f << "error time : " << j << " " << long(time - prevtime) << std::endl;
  152. }
  153. maxsignalledat = MAX(maxsignalledat, long(fMeasure[j].fClientTable[i].fSignaledAt - time));
  154. maxawakedat = MAX(maxawakedat, long(fMeasure[j].fClientTable[i].fAwakeAt - time));
  155. maxfinisheddat = MAX(maxfinisheddat, long(fMeasure[j].fClientTable[i].fFinishedAt - time));
  156. max = true;
  157. }
  158. prevtime = time;
  159. prevcycle = cycle;
  160. }
  161. f << std::endl;
  162. if (max) {
  163. f << "maxsignalledat: " << maxsignalledat
  164. << '\t' << "maxawakedat: " << maxawakedat
  165. << '\t' << "maxfinisheddat: " << maxfinisheddat
  166. << '\t' << std::endl;
  167. }
  168. }
  169. }
  170. f.close();
  171. }
  172. */
  173. }
  174. void JackEngineTiming::ClearTimeMeasures()
  175. {
  176. for (int i = 0; i < TIME_POINTS; i++) {
  177. for (int j = 0; j < CLIENT_NUM; j++) {
  178. fMeasure[i].fClientTable[j].fRefNum = 0;
  179. fMeasure[i].fClientTable[j].fSignaledAt = 0;
  180. fMeasure[i].fClientTable[j].fAwakeAt = 0;
  181. fMeasure[i].fClientTable[j].fFinishedAt = 0;
  182. }
  183. }
  184. fLastTime = fCurTime = 0;
  185. }
  186. } // end of namespace