WMPerfMonTabSystem.Mod 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. MODULE WMPerfMonTabSystem; (** AUTHOR "staubesv"; PURPOSE "Performance Monitor system tab"; *)
  2. IMPORT
  3. Plugins := WMPerfMonPlugins, Perf := WMPerfMonComponents,
  4. Machine, Heaps, Kernel, Commands, Streams, Dates, Strings, UpTime,
  5. WMComponents, WMStandardComponents;
  6. TYPE
  7. SystemTab* = OBJECT(WMComponents.VisualComponent)
  8. VAR
  9. clockrate : LONGINT; (* MHz, -1 if invalid *)
  10. (* GC Statistics *)
  11. gcCurrentRun : Perf.Indicator;
  12. line1, line2, line3 : Perf.Indicator;
  13. (* CPU clock rate detection *)
  14. cpuClockrate : Perf.Indicator;
  15. (* Timers *)
  16. milliTimer : Kernel.MilliTimer;
  17. lastTimestamp : HUGEINT;
  18. lastGcCyclesAllRuns : HUGEINT;
  19. lastNgc : LONGINT;
  20. started : BOOLEAN;
  21. startBtn : WMStandardComponents.Button;
  22. elapsed : Perf.Indicator;
  23. (* System information *)
  24. format : ARRAY 32 OF CHAR;
  25. timeLabel, uptimeLabel : Perf.Indicator;
  26. w : Streams.StringWriter;
  27. (* Performance Monitoring *)
  28. unloadBtn : WMStandardComponents.Button;
  29. timer : Kernel.Timer;
  30. alive, dead : BOOLEAN;
  31. PROCEDURE EstimateClockRate() : LONGINT;
  32. CONST Tries = 10;
  33. VAR
  34. try : LONGINT; done : BOOLEAN; clockrate : LONGINT;
  35. string, nbr : ARRAY 128 OF CHAR;
  36. BEGIN
  37. cpuClockrate.SetCaption(" CPU clock rate estimation...");
  38. try := 1; done := FALSE; clockrate := -1;
  39. WHILE ~done & (try <= Tries) DO
  40. IF Plugins.EstimateCpuClockrate(clockrate) THEN
  41. done := TRUE;
  42. END;
  43. INC(try);
  44. END;
  45. IF done THEN
  46. string := " CPU clock rate is ";
  47. Strings.IntToStr(clockrate, nbr); Strings.Append(string, nbr);
  48. Strings.Append(string, "MHz (estimated)");
  49. cpuClockrate.SetCaption(string);
  50. ELSE
  51. cpuClockrate.SetCaption(" CPU clock rate estimation failed");
  52. END;
  53. RETURN clockrate;
  54. END EstimateClockRate;
  55. PROCEDURE HandleGcButton(sender, data : ANY);
  56. VAR
  57. string, nbr : ARRAY 128 OF CHAR;
  58. lastGcCyclesTot : HUGEINT;
  59. w : Streams.StringWriter;
  60. BEGIN
  61. IF clockrate = -1 THEN clockrate := EstimateClockRate(); END;
  62. lastGcCyclesTot := Heaps.NgcCyclesAllRuns;
  63. Kernel.GC;
  64. string := " Last run: ";
  65. IF clockrate # -1 THEN
  66. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesLastRun, clockrate), nbr);
  67. ELSE
  68. nbr := "Clockrate unkown";
  69. END;
  70. Strings.Append(string, nbr);
  71. gcCurrentRun.SetCaption(string);
  72. (* Number of GC runs & total GC time & max time*)
  73. NEW(w, 128);
  74. w.String("GC Runs: "); w.Int(Heaps.Ngc, 0); w.String(" GC Total Time: ");
  75. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesAllRuns, clockrate), nbr); w.String(nbr);
  76. w.String(" GC longest run: ");
  77. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesMax, clockrate), nbr); w.String(nbr);
  78. w.Get(string);
  79. line1.SetCaption(string);
  80. (* Mark phase *)
  81. w.Reset;
  82. w.String("Mark phase: "); w.Int(Heaps.Nmarked, 0); w.String(" blocks marked in ");
  83. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesMark, clockrate), nbr); w.String(nbr);
  84. w.String(" ("); w.Int(Heaps.Nmark, 0); w.String(" calls to Heaps.Mark)");
  85. w.Get(string);
  86. line2.SetCaption(string);
  87. (* Sweep phase *)
  88. w.Reset;
  89. w.String("Sweep phase: "); w.Int(Heaps.NgcSweeps, 0); w.String(" calls to sweep in ");
  90. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcSweepTime, clockrate), nbr); w.String(nbr);
  91. w.String(" (max ");
  92. Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcSweepMax, clockrate), nbr); w.String(nbr);
  93. w.String(")");
  94. w.Get(string);
  95. line3.SetCaption(string);
  96. END HandleGcButton;
  97. PROCEDURE HandleDetectButton(sender, data : ANY);
  98. BEGIN
  99. clockrate := EstimateClockRate();
  100. END HandleDetectButton;
  101. PROCEDURE HandleTimerButton(sender, data : ANY);
  102. VAR string, nbr : ARRAY 128 OF CHAR; msTicks, msTimestamp, msGc, msDiff : LONGINT;
  103. BEGIN
  104. IF clockrate = -1 THEN clockrate := EstimateClockRate(); END;
  105. IF started THEN
  106. started := FALSE; startBtn.caption.SetAOC("Start");
  107. string := " Time elapsed: ";
  108. msTicks := Kernel.Elapsed(milliTimer);
  109. msTimestamp := Plugins.CyclesToMs(Machine.GetTimer() - lastTimestamp, clockrate);
  110. Plugins.MsToString(msTicks, nbr);
  111. Strings.Append(string, nbr); Strings.Append(string, " (Ticks), ");
  112. Plugins.MsToString(msTimestamp ,nbr);
  113. Strings.Append(string, nbr); Strings.Append(string, " (Timestamps), ");
  114. Strings.Append(string, "TimeDiff: ");
  115. msDiff := msTimestamp - msTicks; IF msDiff < 0 THEN msDiff := -msDiff; END;
  116. Plugins.MsToString(msDiff, nbr);
  117. Strings.Append(string, nbr);
  118. Strings.Append(string, ", GC Time: ");
  119. msGc := Plugins.CyclesToMs(Heaps.NgcCyclesAllRuns - lastGcCyclesAllRuns, clockrate);
  120. Plugins.MsToString(msGc, nbr); Strings.Append(string, nbr);
  121. Strings.Append(string, ", GC Runs: ");
  122. Strings.IntToStr(Heaps.Ngc - lastNgc, nbr); Strings.Append(string, nbr);
  123. elapsed.SetCaption(string);
  124. ELSE
  125. started := TRUE; startBtn.caption.SetAOC("Stop");
  126. Kernel.SetTimer(milliTimer, 0);
  127. lastTimestamp := Machine.GetTimer();
  128. lastGcCyclesAllRuns := Heaps.NgcCyclesAllRuns;
  129. lastNgc := Heaps.Ngc;
  130. elapsed.SetCaption(" Timer is running...");
  131. END;
  132. END HandleTimerButton;
  133. PROCEDURE HandleUnloadButton(sender, data : ANY);
  134. VAR msg : ARRAY 128 OF CHAR; res : LONGINT;
  135. BEGIN
  136. Commands.Call("SystemTools.FreeDownTo WMPerfMonPlugins", {}, res, msg);
  137. END HandleUnloadButton;
  138. PROCEDURE CreateSysinfoPanel() : WMStandardComponents.Panel;
  139. VAR
  140. panel, line : WMStandardComponents.Panel; label : WMStandardComponents.Label;
  141. caption : ARRAY 128 OF CHAR;
  142. PROCEDURE AppendBoolean(VAR string : ARRAY OF CHAR; value : BOOLEAN);
  143. BEGIN
  144. IF value THEN
  145. Strings.Append(string, "Yes");
  146. ELSE
  147. Strings.Append(string, "No");
  148. END;
  149. END AppendBoolean;
  150. BEGIN
  151. panel := Perf.NewGroupPanel("System Information", WMComponents.AlignTop, 100);
  152. (* First Line: Version *)
  153. line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
  154. label := Perf.NewLabel("Version:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
  155. label := Perf.NewLabel(Machine.version, WMComponents.AlignClient, 0, 0); line.AddContent(label);
  156. (* Second Line: System Time *)
  157. line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
  158. label := Perf.NewLabel("System Time:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
  159. timeLabel := Perf.NewIndicator("--", WMComponents.AlignClient, 0, 0); line.AddContent(timeLabel);
  160. (* Third Line: System Start time and up time *)
  161. line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
  162. label := Perf.NewLabel("Start Time: ", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
  163. Strings.FormatDateTime(format, UpTime.GetStartTime(), caption);
  164. label := Perf.NewLabel(caption, WMComponents.AlignLeft, 210, 0); line.AddContent(label);
  165. uptimeLabel := Perf.NewIndicator("--", WMComponents.AlignClient, 0, 0); line.AddContent(uptimeLabel);
  166. (* 4th Line: MMX/SSE/SSE2 capabilities *)
  167. line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
  168. label := Perf.NewLabel("Capabilities:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
  169. caption := "MMX: "; AppendBoolean(caption, Machine.MMX IN Machine.features);
  170. Strings.Append(caption, ", SSE: "); AppendBoolean(caption, Machine.SSESupport);
  171. Strings.Append(caption, ", SSE2: "); AppendBoolean(caption, Machine.SSE2Support);
  172. label := Perf.NewLabel(caption, WMComponents.AlignClient, 0, 0); line.AddContent(label);
  173. RETURN panel;
  174. END CreateSysinfoPanel;
  175. PROCEDURE CreateGcStatisticsPanel() : WMStandardComponents.Panel;
  176. VAR panel : WMStandardComponents.Panel; line : WMStandardComponents.Panel;
  177. BEGIN
  178. panel := Perf.NewGroupPanel("Garbage Collector", WMComponents.AlignTop, 120);
  179. line := Perf.NewPanel(WMComponents.AlignTop, 0, 20); panel.AddContent(line);
  180. line.AddContent(Perf.NewButton("Run GC", HandleGcButton));
  181. gcCurrentRun := Perf.NewIndicator("", WMComponents.AlignClient, 0, 0);
  182. line.AddContent(gcCurrentRun);
  183. line1 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line1);
  184. line2 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line2);
  185. line3 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line3);
  186. RETURN panel;
  187. END CreateGcStatisticsPanel;
  188. PROCEDURE CreateCPUClockratePanel() : WMStandardComponents.Panel;
  189. VAR panel : WMStandardComponents.Panel;
  190. BEGIN
  191. panel := Perf.NewGroupPanel("CPU Clockrate", WMComponents.AlignTop, 45);
  192. panel.AddContent(Perf.NewButton("Detect", HandleDetectButton));
  193. cpuClockrate := Perf.NewIndicator(" Press button to detect CPU clockrate", WMComponents.AlignClient, 0, 0);
  194. panel.AddContent(cpuClockrate);
  195. RETURN panel;
  196. END CreateCPUClockratePanel;
  197. PROCEDURE CreateTimerPanel() : WMStandardComponents.Panel;
  198. VAR panel : WMStandardComponents.Panel;
  199. BEGIN
  200. panel := Perf.NewGroupPanel("Timers", WMComponents.AlignTop, 45);
  201. startBtn := Perf.NewButton("Start", HandleTimerButton); panel.AddContent(startBtn);
  202. elapsed := Perf.NewIndicator(" Press button to start time...", WMComponents.AlignClient, 0, 0); panel.AddContent(elapsed);
  203. RETURN panel;
  204. END CreateTimerPanel;
  205. PROCEDURE CreateUnloadPanel() : WMStandardComponents.Panel;
  206. VAR panel : WMStandardComponents.Panel;
  207. BEGIN
  208. panel := Perf.NewGroupPanel("Performance Monitoring", WMComponents.AlignTop, 45);
  209. unloadBtn := Perf.NewButton("Unload", HandleUnloadButton); panel.AddContent(unloadBtn);
  210. panel.AddContent(Perf.NewLabel(" Window close button just closes GUI. This closes all.", WMComponents.AlignClient, 0, 0));
  211. RETURN panel;
  212. END CreateUnloadPanel;
  213. PROCEDURE UpdateTime;
  214. VAR caption : ARRAY 64 OF CHAR;
  215. BEGIN
  216. (* System Time *)
  217. Strings.FormatDateTime(format, Dates.Now(), caption);
  218. timeLabel.SetCaption(caption);
  219. (* System Uptime *)
  220. w.Reset;
  221. w.String(" (Uptime: "); UpTime.ToStream(w); w.Char(")");
  222. w.Get(caption);
  223. uptimeLabel.SetCaption(caption);
  224. END UpdateTime;
  225. PROCEDURE Finalize*;
  226. BEGIN
  227. alive := FALSE;
  228. timer.Wakeup;
  229. BEGIN {EXCLUSIVE} AWAIT(dead); END;
  230. Finalize^;
  231. END Finalize;
  232. PROCEDURE &Init*;
  233. BEGIN
  234. Init^;
  235. SetNameAsString(StrSystemTab);
  236. NEW(timer); alive := TRUE; dead := FALSE;
  237. NEW(w, 64);
  238. format := "hh:nn:ss, wwww, mmmm d, yyyy";
  239. clockrate := -1; (* invalid *)
  240. AddContent(CreateSysinfoPanel());
  241. AddContent(CreateCPUClockratePanel());
  242. AddContent(CreateGcStatisticsPanel());
  243. AddContent(CreateTimerPanel());
  244. AddContent(CreateUnloadPanel());
  245. END Init;
  246. BEGIN {ACTIVE}
  247. WHILE alive DO
  248. IF visible.Get() THEN UpdateTime; END;
  249. timer.Sleep(500);
  250. END;
  251. BEGIN {EXCLUSIVE} dead := TRUE; END;
  252. END SystemTab;
  253. VAR
  254. StrSystemTab : Strings.String;
  255. BEGIN
  256. StrSystemTab := Strings.NewString("SystemTab");
  257. END WMPerfMonTabSystem.