123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- MODULE WMPerfMonTabSystem; (** AUTHOR "staubesv"; PURPOSE "Performance Monitor system tab"; *)
- IMPORT
- Plugins := WMPerfMonPlugins, Perf := WMPerfMonComponents,
- Machine, Heaps, Kernel, Commands, Streams, Dates, Strings, UpTime,
- WMComponents, WMStandardComponents;
- TYPE
- SystemTab* = OBJECT(WMComponents.VisualComponent)
- VAR
- clockrate : LONGINT; (* MHz, -1 if invalid *)
- (* GC Statistics *)
- gcCurrentRun : Perf.Indicator;
- line1, line2, line3 : Perf.Indicator;
- (* CPU clock rate detection *)
- cpuClockrate : Perf.Indicator;
- (* Timers *)
- milliTimer : Kernel.MilliTimer;
- lastTimestamp : HUGEINT;
- lastGcCyclesAllRuns : HUGEINT;
- lastNgc : LONGINT;
- started : BOOLEAN;
- startBtn : WMStandardComponents.Button;
- elapsed : Perf.Indicator;
- (* System information *)
- format : ARRAY 32 OF CHAR;
- timeLabel, uptimeLabel : Perf.Indicator;
- w : Streams.StringWriter;
- (* Performance Monitoring *)
- unloadBtn : WMStandardComponents.Button;
- timer : Kernel.Timer;
- alive, dead : BOOLEAN;
- PROCEDURE EstimateClockRate() : LONGINT;
- CONST Tries = 10;
- VAR
- try : LONGINT; done : BOOLEAN; clockrate : LONGINT;
- string, nbr : ARRAY 128 OF CHAR;
- BEGIN
- cpuClockrate.SetCaption(" CPU clock rate estimation...");
- try := 1; done := FALSE; clockrate := -1;
- WHILE ~done & (try <= Tries) DO
- IF Plugins.EstimateCpuClockrate(clockrate) THEN
- done := TRUE;
- END;
- INC(try);
- END;
- IF done THEN
- string := " CPU clock rate is ";
- Strings.IntToStr(clockrate, nbr); Strings.Append(string, nbr);
- Strings.Append(string, "MHz (estimated)");
- cpuClockrate.SetCaption(string);
- ELSE
- cpuClockrate.SetCaption(" CPU clock rate estimation failed");
- END;
- RETURN clockrate;
- END EstimateClockRate;
- PROCEDURE HandleGcButton(sender, data : ANY);
- VAR
- string, nbr : ARRAY 128 OF CHAR;
- lastGcCyclesTot : HUGEINT;
- w : Streams.StringWriter;
- BEGIN
- IF clockrate = -1 THEN clockrate := EstimateClockRate(); END;
- lastGcCyclesTot := Heaps.NgcCyclesAllRuns;
- Kernel.GC;
- string := " Last run: ";
- IF clockrate # -1 THEN
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesLastRun, clockrate), nbr);
- ELSE
- nbr := "Clockrate unkown";
- END;
- Strings.Append(string, nbr);
- gcCurrentRun.SetCaption(string);
- (* Number of GC runs & total GC time & max time*)
- NEW(w, 128);
- w.String("GC Runs: "); w.Int(Heaps.Ngc, 0); w.String(" GC Total Time: ");
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesAllRuns, clockrate), nbr); w.String(nbr);
- w.String(" GC longest run: ");
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesMax, clockrate), nbr); w.String(nbr);
- w.Get(string);
- line1.SetCaption(string);
- (* Mark phase *)
- w.Reset;
- w.String("Mark phase: "); w.Int(Heaps.Nmarked, 0); w.String(" blocks marked in ");
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcCyclesMark, clockrate), nbr); w.String(nbr);
- w.String(" ("); w.Int(Heaps.Nmark, 0); w.String(" calls to Heaps.Mark)");
- w.Get(string);
- line2.SetCaption(string);
- (* Sweep phase *)
- w.Reset;
- w.String("Sweep phase: "); w.Int(Heaps.NgcSweeps, 0); w.String(" calls to sweep in ");
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcSweepTime, clockrate), nbr); w.String(nbr);
- w.String(" (max ");
- Plugins.MsToString(Plugins.CyclesToMs(Heaps.NgcSweepMax, clockrate), nbr); w.String(nbr);
- w.String(")");
- w.Get(string);
- line3.SetCaption(string);
- END HandleGcButton;
- PROCEDURE HandleDetectButton(sender, data : ANY);
- BEGIN
- clockrate := EstimateClockRate();
- END HandleDetectButton;
- PROCEDURE HandleTimerButton(sender, data : ANY);
- VAR string, nbr : ARRAY 128 OF CHAR; msTicks, msTimestamp, msGc, msDiff : LONGINT;
- BEGIN
- IF clockrate = -1 THEN clockrate := EstimateClockRate(); END;
- IF started THEN
- started := FALSE; startBtn.caption.SetAOC("Start");
- string := " Time elapsed: ";
- msTicks := Kernel.Elapsed(milliTimer);
- msTimestamp := Plugins.CyclesToMs(Machine.GetTimer() - lastTimestamp, clockrate);
- Plugins.MsToString(msTicks, nbr);
- Strings.Append(string, nbr); Strings.Append(string, " (Ticks), ");
- Plugins.MsToString(msTimestamp ,nbr);
- Strings.Append(string, nbr); Strings.Append(string, " (Timestamps), ");
- Strings.Append(string, "TimeDiff: ");
- msDiff := msTimestamp - msTicks; IF msDiff < 0 THEN msDiff := -msDiff; END;
- Plugins.MsToString(msDiff, nbr);
- Strings.Append(string, nbr);
- Strings.Append(string, ", GC Time: ");
- msGc := Plugins.CyclesToMs(Heaps.NgcCyclesAllRuns - lastGcCyclesAllRuns, clockrate);
- Plugins.MsToString(msGc, nbr); Strings.Append(string, nbr);
- Strings.Append(string, ", GC Runs: ");
- Strings.IntToStr(Heaps.Ngc - lastNgc, nbr); Strings.Append(string, nbr);
- elapsed.SetCaption(string);
- ELSE
- started := TRUE; startBtn.caption.SetAOC("Stop");
- Kernel.SetTimer(milliTimer, 0);
- lastTimestamp := Machine.GetTimer();
- lastGcCyclesAllRuns := Heaps.NgcCyclesAllRuns;
- lastNgc := Heaps.Ngc;
- elapsed.SetCaption(" Timer is running...");
- END;
- END HandleTimerButton;
- PROCEDURE HandleUnloadButton(sender, data : ANY);
- VAR msg : ARRAY 128 OF CHAR; res : LONGINT;
- BEGIN
- Commands.Call("SystemTools.FreeDownTo WMPerfMonPlugins", {}, res, msg);
- END HandleUnloadButton;
- PROCEDURE CreateSysinfoPanel() : WMStandardComponents.Panel;
- VAR
- panel, line : WMStandardComponents.Panel; label : WMStandardComponents.Label;
- caption : ARRAY 128 OF CHAR;
- PROCEDURE AppendBoolean(VAR string : ARRAY OF CHAR; value : BOOLEAN);
- BEGIN
- IF value THEN
- Strings.Append(string, "Yes");
- ELSE
- Strings.Append(string, "No");
- END;
- END AppendBoolean;
- BEGIN
- panel := Perf.NewGroupPanel("System Information", WMComponents.AlignTop, 100);
- (* First Line: Version *)
- line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
- label := Perf.NewLabel("Version:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
- label := Perf.NewLabel(Machine.version, WMComponents.AlignClient, 0, 0); line.AddContent(label);
- (* Second Line: System Time *)
- line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
- label := Perf.NewLabel("System Time:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
- timeLabel := Perf.NewIndicator("--", WMComponents.AlignClient, 0, 0); line.AddContent(timeLabel);
- (* Third Line: System Start time and up time *)
- line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
- label := Perf.NewLabel("Start Time: ", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
- Strings.FormatDateTime(format, UpTime.GetStartTime(), caption);
- label := Perf.NewLabel(caption, WMComponents.AlignLeft, 210, 0); line.AddContent(label);
- uptimeLabel := Perf.NewIndicator("--", WMComponents.AlignClient, 0, 0); line.AddContent(uptimeLabel);
- (* 4th Line: MMX/SSE/SSE2 capabilities *)
- line := Perf.NewPanel(WMComponents.AlignTop, 0, Perf.LineHeight); panel.AddContent(line);
- label := Perf.NewLabel("Capabilities:", WMComponents.AlignLeft, 100, 0); line.AddContent(label);
- caption := "MMX: "; AppendBoolean(caption, Machine.MMX IN Machine.features);
- Strings.Append(caption, ", SSE: "); AppendBoolean(caption, Machine.SSESupport);
- Strings.Append(caption, ", SSE2: "); AppendBoolean(caption, Machine.SSE2Support);
- label := Perf.NewLabel(caption, WMComponents.AlignClient, 0, 0); line.AddContent(label);
- RETURN panel;
- END CreateSysinfoPanel;
- PROCEDURE CreateGcStatisticsPanel() : WMStandardComponents.Panel;
- VAR panel : WMStandardComponents.Panel; line : WMStandardComponents.Panel;
- BEGIN
- panel := Perf.NewGroupPanel("Garbage Collector", WMComponents.AlignTop, 120);
- line := Perf.NewPanel(WMComponents.AlignTop, 0, 20); panel.AddContent(line);
- line.AddContent(Perf.NewButton("Run GC", HandleGcButton));
- gcCurrentRun := Perf.NewIndicator("", WMComponents.AlignClient, 0, 0);
- line.AddContent(gcCurrentRun);
- line1 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line1);
- line2 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line2);
- line3 := Perf.NewIndicator("", WMComponents.AlignTop, 0, 20); panel.AddContent(line3);
- RETURN panel;
- END CreateGcStatisticsPanel;
- PROCEDURE CreateCPUClockratePanel() : WMStandardComponents.Panel;
- VAR panel : WMStandardComponents.Panel;
- BEGIN
- panel := Perf.NewGroupPanel("CPU Clockrate", WMComponents.AlignTop, 45);
- panel.AddContent(Perf.NewButton("Detect", HandleDetectButton));
- cpuClockrate := Perf.NewIndicator(" Press button to detect CPU clockrate", WMComponents.AlignClient, 0, 0);
- panel.AddContent(cpuClockrate);
- RETURN panel;
- END CreateCPUClockratePanel;
- PROCEDURE CreateTimerPanel() : WMStandardComponents.Panel;
- VAR panel : WMStandardComponents.Panel;
- BEGIN
- panel := Perf.NewGroupPanel("Timers", WMComponents.AlignTop, 45);
- startBtn := Perf.NewButton("Start", HandleTimerButton); panel.AddContent(startBtn);
- elapsed := Perf.NewIndicator(" Press button to start time...", WMComponents.AlignClient, 0, 0); panel.AddContent(elapsed);
- RETURN panel;
- END CreateTimerPanel;
- PROCEDURE CreateUnloadPanel() : WMStandardComponents.Panel;
- VAR panel : WMStandardComponents.Panel;
- BEGIN
- panel := Perf.NewGroupPanel("Performance Monitoring", WMComponents.AlignTop, 45);
- unloadBtn := Perf.NewButton("Unload", HandleUnloadButton); panel.AddContent(unloadBtn);
- panel.AddContent(Perf.NewLabel(" Window close button just closes GUI. This closes all.", WMComponents.AlignClient, 0, 0));
- RETURN panel;
- END CreateUnloadPanel;
- PROCEDURE UpdateTime;
- VAR caption : ARRAY 64 OF CHAR;
- BEGIN
- (* System Time *)
- Strings.FormatDateTime(format, Dates.Now(), caption);
- timeLabel.SetCaption(caption);
- (* System Uptime *)
- w.Reset;
- w.String(" (Uptime: "); UpTime.ToStream(w); w.Char(")");
- w.Get(caption);
- uptimeLabel.SetCaption(caption);
- END UpdateTime;
- PROCEDURE Finalize*;
- BEGIN
- alive := FALSE;
- timer.Wakeup;
- BEGIN {EXCLUSIVE} AWAIT(dead); END;
- Finalize^;
- END Finalize;
- PROCEDURE &Init*;
- BEGIN
- Init^;
- SetNameAsString(StrSystemTab);
- NEW(timer); alive := TRUE; dead := FALSE;
- NEW(w, 64);
- format := "hh:nn:ss, wwww, mmmm d, yyyy";
- clockrate := -1; (* invalid *)
- AddContent(CreateSysinfoPanel());
- AddContent(CreateCPUClockratePanel());
- AddContent(CreateGcStatisticsPanel());
- AddContent(CreateTimerPanel());
- AddContent(CreateUnloadPanel());
- END Init;
- BEGIN {ACTIVE}
- WHILE alive DO
- IF visible.Get() THEN UpdateTime; END;
- timer.Sleep(500);
- END;
- BEGIN {EXCLUSIVE} dead := TRUE; END;
- END SystemTab;
- VAR
- StrSystemTab : Strings.String;
- BEGIN
- StrSystemTab := Strings.NewString("SystemTab");
- END WMPerfMonTabSystem.
|