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.

331 lines
15KB

  1. /*
  2. Copyright (C) 2008 Grame & RTL
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #include "JackEngineProfiling.h"
  16. #include "JackGraphManager.h"
  17. #include "JackClientControl.h"
  18. #include "JackClientInterface.h"
  19. #include "JackTime.h"
  20. namespace Jack
  21. {
  22. JackEngineProfiling::JackEngineProfiling():fAudioCycle(0)
  23. {
  24. jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
  25. // Force memory page in
  26. memset(fProfileTable, 0, sizeof(fProfileTable));
  27. }
  28. JackEngineProfiling::~JackEngineProfiling()
  29. {
  30. // Window monitoring
  31. int max_client = 0;
  32. char buffer[1024];
  33. char* nameTable[CLIENT_NUM];
  34. FILE* file = fopen("JackEngineProfiling.log", "w");
  35. jack_info("Write server and clients timing data...");
  36. if (file == NULL) {
  37. jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
  38. } else {
  39. for (int i = 2; i < TIME_POINTS; i++) {
  40. bool header = true;
  41. bool printed = false;
  42. int count = 0;
  43. for (int j = REAL_REFNUM; j < CLIENT_NUM; j++) {
  44. if (fProfileTable[i].fClientTable[j].fRefNum > 0) {
  45. long d1 = long(fProfileTable[i - 1].fCurCycleBegin - fProfileTable[i - 2].fCurCycleBegin);
  46. long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
  47. if (d1 > 0 && fProfileTable[i].fClientTable[j].fStatus != NotTriggered) { // Valid cycle
  48. count++;
  49. nameTable[count] = fNameTable[fProfileTable[i].fClientTable[j].fRefNum];
  50. // driver delta and end cycle
  51. if (header) {
  52. fprintf(file, "%ld \t %ld \t", d1, d2);
  53. header = false;
  54. }
  55. long d5 = long(fProfileTable[i].fClientTable[j].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
  56. long d6 = long(fProfileTable[i].fClientTable[j].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
  57. long d7 = long(fProfileTable[i].fClientTable[j].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
  58. // ref, signal, start, end, scheduling, duration, status
  59. fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t",
  60. fProfileTable[i].fClientTable[j].fRefNum,
  61. ((d5 > 0) ? d5 : 0),
  62. ((d6 > 0) ? d6 : 0),
  63. ((d7 > 0) ? d7 : 0),
  64. ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0),
  65. ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0),
  66. fProfileTable[i].fClientTable[j].fStatus);
  67. printed = true;
  68. }
  69. }
  70. max_client = (count > max_client) ? count : max_client;
  71. }
  72. if (printed) {
  73. fprintf(file, "\n");
  74. } else if (fProfileTable[i].fAudioCycle > 0) { // Driver timing only
  75. long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
  76. long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
  77. if (d1 > 0) { // Valid cycle
  78. fprintf(file, "%ld \t %ld \n", d1, d2);
  79. }
  80. }
  81. }
  82. fclose(file);
  83. }
  84. // Driver period
  85. file = fopen("Timing1.plot", "w");
  86. if (file == NULL) {
  87. jack_error("JackEngineProfiling::Save cannot open Timing1.log file");
  88. } else {
  89. fprintf(file, "set grid\n");
  90. fprintf(file, "set title \"Audio driver timing\"\n");
  91. fprintf(file, "set xlabel \"audio cycles\"\n");
  92. fprintf(file, "set ylabel \"usec\"\n");
  93. fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
  94. fprintf(file, "set output 'Timing1.pdf\n");
  95. fprintf(file, "set terminal pdf\n");
  96. fprintf(file, "set grid\n");
  97. fprintf(file, "set title \"Audio driver timing\"\n");
  98. fprintf(file, "set xlabel \"audio cycles\"\n");
  99. fprintf(file, "set ylabel \"usec\"\n");
  100. fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n");
  101. fclose(file);
  102. }
  103. // Driver end date
  104. file = fopen("Timing2.plot", "w");
  105. if (file == NULL) {
  106. jack_error("JackEngineProfiling::Save cannot open Timing2.log file");
  107. } else {
  108. fprintf(file, "set grid\n");
  109. fprintf(file, "set title \"Driver end date\"\n");
  110. fprintf(file, "set xlabel \"audio cycles\"\n");
  111. fprintf(file, "set ylabel \"usec\"\n");
  112. fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
  113. fprintf(file, "set output 'Timing2.pdf\n");
  114. fprintf(file, "set terminal pdf\n");
  115. fprintf(file, "set grid\n");
  116. fprintf(file, "set title \"Driver end date\"\n");
  117. fprintf(file, "set xlabel \"audio cycles\"\n");
  118. fprintf(file, "set ylabel \"usec\"\n");
  119. fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n");
  120. fclose(file);
  121. }
  122. // Clients end date
  123. if (max_client > 0) {
  124. file = fopen("Timing3.plot", "w");
  125. if (file == NULL) {
  126. jack_error("JackEngineProfiling::Save cannot open Timing3.log file");
  127. } else {
  128. fprintf(file, "set multiplot\n");
  129. fprintf(file, "set grid\n");
  130. fprintf(file, "set title \"Clients end date\"\n");
  131. fprintf(file, "set xlabel \"audio cycles\"\n");
  132. fprintf(file, "set ylabel \"usec\"\n");
  133. fprintf(file, "plot ");
  134. for (int i = 0; i < max_client; i++) {
  135. if (i == 0) {
  136. if ((i + 1) == max_client) {
  137. sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
  138. ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  139. } else {
  140. sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
  141. ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  142. }
  143. } else if ((i + 1) == max_client) { // Last client
  144. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  145. } else {
  146. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
  147. }
  148. fprintf(file, buffer);
  149. }
  150. fprintf(file, "\n unset multiplot\n");
  151. fprintf(file, "set output 'Timing3.pdf\n");
  152. fprintf(file, "set terminal pdf\n");
  153. fprintf(file, "set multiplot\n");
  154. fprintf(file, "set grid\n");
  155. fprintf(file, "set title \"Clients end date\"\n");
  156. fprintf(file, "set xlabel \"audio cycles\"\n");
  157. fprintf(file, "set ylabel \"usec\"\n");
  158. fprintf(file, "plot ");
  159. for (int i = 0; i < max_client; i++) {
  160. if (i == 0) {
  161. if ((i + 1) == max_client) {
  162. sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines",
  163. ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  164. } else {
  165. sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,",
  166. ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  167. }
  168. } else if ((i + 1) == max_client) { // Last client
  169. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]);
  170. } else {
  171. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]);
  172. }
  173. fprintf(file, buffer);
  174. }
  175. fclose(file);
  176. }
  177. }
  178. // Clients scheduling
  179. if (max_client > 0) {
  180. file = fopen("Timing4.plot", "w");
  181. if (file == NULL) {
  182. jack_error("JackEngineProfiling::Save cannot open Timing4.log file");
  183. } else {
  184. fprintf(file, "set multiplot\n");
  185. fprintf(file, "set grid\n");
  186. fprintf(file, "set title \"Clients scheduling latency\"\n");
  187. fprintf(file, "set xlabel \"audio cycles\"\n");
  188. fprintf(file, "set ylabel \"usec\"\n");
  189. fprintf(file, "plot ");
  190. for (int i = 0; i < max_client; i++) {
  191. if ((i + 1) == max_client) // Last client
  192. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
  193. else
  194. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
  195. fprintf(file, buffer);
  196. }
  197. fprintf(file, "\n unset multiplot\n");
  198. fprintf(file, "set output 'Timing4.pdf\n");
  199. fprintf(file, "set terminal pdf\n");
  200. fprintf(file, "set multiplot\n");
  201. fprintf(file, "set grid\n");
  202. fprintf(file, "set title \"Clients scheduling latency\"\n");
  203. fprintf(file, "set xlabel \"audio cycles\"\n");
  204. fprintf(file, "set ylabel \"usec\"\n");
  205. fprintf(file, "plot ");
  206. for (int i = 0; i < max_client; i++) {
  207. if ((i + 1) == max_client) // Last client
  208. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]);
  209. else
  210. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]);
  211. fprintf(file, buffer);
  212. }
  213. fclose(file);
  214. }
  215. }
  216. // Clients duration
  217. if (max_client > 0) {
  218. file = fopen("Timing5.plot", "w");
  219. if (file == NULL) {
  220. jack_error("JackEngineProfiling::Save cannot open Timing5.log file");
  221. } else {
  222. fprintf(file, "set multiplot\n");
  223. fprintf(file, "set grid\n");
  224. fprintf(file, "set title \"Clients duration\"\n");
  225. fprintf(file, "set xlabel \"audio cycles\"\n");
  226. fprintf(file, "set ylabel \"usec\"\n");
  227. fprintf(file, "plot ");
  228. for (int i = 0; i < max_client; i++) {
  229. if ((i + 1) == max_client) // Last client
  230. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
  231. else
  232. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
  233. fprintf(file, buffer);
  234. }
  235. fprintf(file, "\n unset multiplot\n");
  236. fprintf(file, "set output 'Timing5.pdf\n");
  237. fprintf(file, "set terminal pdf\n");
  238. fprintf(file, "set multiplot\n");
  239. fprintf(file, "set grid\n");
  240. fprintf(file, "set title \"Clients duration\"\n");
  241. fprintf(file, "set xlabel \"audio cycles\"\n");
  242. fprintf(file, "set ylabel \"usec\"\n");
  243. fprintf(file, "plot ");
  244. for (int i = 0; i < max_client; i++) {
  245. if ((i + 1) == max_client) // Last client
  246. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
  247. else
  248. sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]);
  249. fprintf(file, buffer);
  250. }
  251. fclose(file);
  252. }
  253. }
  254. }
  255. void JackEngineProfiling::Profile(JackClientInterface** table,
  256. JackGraphManager* manager,
  257. jack_time_t period_usecs,
  258. jack_time_t cur_cycle_begin,
  259. jack_time_t prev_cycle_end)
  260. {
  261. fAudioCycle = (fAudioCycle + 1) % TIME_POINTS;
  262. // Keeps cycle data
  263. fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs;
  264. fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin;
  265. fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
  266. fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;
  267. for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
  268. JackClientInterface* client = table[i];
  269. JackClientTiming* timing = manager->GetClientTiming(i);
  270. if (client && client->GetClientControl()->fActive) {
  271. strcpy(fNameTable[i], client->GetClientControl()->fName);
  272. fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i;
  273. fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt;
  274. fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt;
  275. fProfileTable[fAudioCycle].fClientTable[i].fFinishedAt = timing->fFinishedAt;
  276. fProfileTable[fAudioCycle].fClientTable[i].fStatus = timing->fStatus;
  277. }
  278. }
  279. }
  280. JackTimingMeasure* JackEngineProfiling::GetCurMeasure()
  281. {
  282. return &fProfileTable[fAudioCycle];
  283. }
  284. } // end of namespace