BIOS.AMD64.BenchInterrupts.Mod 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. MODULE BenchInterrupts; (** AUTHOR "staubesv"; PURPOSE "Interrupt latency benchmarks"; *)
  2. (**
  3. Non-comrehensive list of aspects to be considered:
  4. - The garbage collector prohibits interrupts while running. Depending on the current state of the heap, this can
  5. introduce delays in the order of seconds
  6. - There can be multipe handlers per interrupt vector
  7. - The Machine.SoftInt is a temporary interrupt vector that is potentially used by other applications
  8. - Result is dependent on other interrupts that have a higher priority and can interrupt our handler
  9. *)
  10. IMPORT
  11. SYSTEM,
  12. Machine, Heaps, Streams, Commands, MathL;
  13. CONST
  14. (* Interrupt vector number for 1st level interrupt handler benchmark
  15. This is a temporary interrupt vector number that is potentially used for different purposes *)
  16. InterruptVectorNumber = Machine.SoftInt;
  17. MinNofSamples = 1000;
  18. MaxNofSamples = 1000000;
  19. VAR
  20. mhz : LONGINT;
  21. start, stop : HUGEINT;
  22. ngc : LONGINT;
  23. data : POINTER TO ARRAY OF LONGINT;
  24. PROCEDURE InterruptHandler(VAR state: Machine.State);
  25. BEGIN
  26. stop := Machine.GetTimer();
  27. END InterruptHandler;
  28. (* Software interrupt call *)
  29. PROCEDURE -SoftwareInterrupt;
  30. CODE {SYSTEM.AMD64}
  31. INT InterruptVectorNumber
  32. END SoftwareInterrupt;
  33. (** Start the 1st Level Interrupt Handler latency benchmark *)
  34. PROCEDURE Bench*(context : Commands.Context); (** [nofSamples] ~ *)
  35. VAR nofSamples, index, oldNgc, ignore : LONGINT;
  36. BEGIN {EXCLUSIVE}
  37. context.arg.GetInteger(nofSamples, FALSE);
  38. IF (nofSamples < MinNofSamples) THEN nofSamples := MinNofSamples;
  39. ELSIF (nofSamples > MaxNofSamples) THEN nofSamples := MaxNofSamples;
  40. END;
  41. context.out.String("Starting 1st level interrupt handler latency benchmark (");
  42. context.out.Int(nofSamples, 0); context.out.String(" samples) ... ");
  43. context.out.Update;
  44. NEW(data, nofSamples);
  45. Machine.InstallHandler(InterruptHandler, InterruptVectorNumber);
  46. ignore := Machine.AcquirePreemption();
  47. oldNgc := Heaps.Ngc;
  48. FOR index := 0 TO LEN(data)-1 DO
  49. start := Machine.GetTimer();
  50. SoftwareInterrupt;
  51. data[index] := SHORT(stop - start);
  52. END;
  53. ngc := Heaps.Ngc - oldNgc;
  54. Machine.ReleasePreemption;
  55. Machine.RemoveHandler(InterruptHandler, InterruptVectorNumber);
  56. context.out.String("done."); context.out.Ln;
  57. END Bench;
  58. PROCEDURE CyclesToMs(cycles : HUGEINT; mhz : LONGINT) : LONGREAL;
  59. BEGIN
  60. RETURN LONGREAL(cycles) / (1000*mhz);
  61. END CyclesToMs;
  62. PROCEDURE ShowMs(cycles : HUGEINT; out : Streams.Writer);
  63. BEGIN
  64. IF (mhz # 0) THEN
  65. out.String(" ("); out.FloatFix(CyclesToMs(cycles, mhz), 0, 6, 0); out.String(" ms)");
  66. END;
  67. END ShowMs;
  68. (** Show the results of the last benchmark run *)
  69. PROCEDURE Show*(context : Commands.Context); (** mhz ~ *)
  70. VAR
  71. nofSamples, min, avg, max, i : LONGINT; sum : HUGEINT;
  72. diff, diffSum, standardDeviation : LONGREAL;
  73. BEGIN {EXCLUSIVE}
  74. context.arg.GetInteger(mhz, FALSE);
  75. IF (data # NIL) THEN
  76. nofSamples := LEN(data);
  77. min := MAX(LONGINT); max := MIN(LONGINT); sum := 0;
  78. (* calculate min, max and sum *)
  79. FOR i := 0 TO LEN(data)-1 DO
  80. IF (data[i] < min) THEN min := data[i];
  81. ELSIF (data[i] > max) THEN max := data[i];
  82. END;
  83. sum := sum + data[i];
  84. END;
  85. avg := SHORT(sum DIV nofSamples);
  86. (* calculate standard deviation *)
  87. diffSum := 0;
  88. FOR i := 0 TO LEN(data)-1 DO
  89. diff := avg - data[i];
  90. diffSum := diffSum + (diff * diff);
  91. END;
  92. standardDeviation := MathL.sqrt(diffSum / nofSamples);
  93. context.out.String("NofSamples: "); context.out.Int(nofSamples, 0); context.out.Ln;
  94. context.out.String("Nof GC runs while benchmarking: "); context.out.Int(ngc, 0); context.out.Ln;
  95. context.out.String("CPU clock rate: ");
  96. IF (mhz # 0) THEN context.out.Int(mhz, 0); context.out.String(" MHz"); ELSE context.out.String("Unknown"); END;
  97. context.out.Ln;
  98. context.out.String("Interrupt Latency in CPU cycles: "); context.out.Ln;
  99. context.out.String("Min: "); context.out.Int(min, 0); ShowMs(min, context.out); context.out.Ln;
  100. context.out.String("Max: "); context.out.Int(max, 0); ShowMs(max, context.out); context.out.Ln;
  101. context.out.String("Avg: "); context.out.Int(avg, 0); ShowMs(avg, context.out); context.out.Ln;
  102. context.out.String("Standard Deviation: "); context.out.FloatFix(standardDeviation, 0, 0, 0); context.out.Ln;
  103. ELSE
  104. context.out.String("No data available."); context.out.Ln;
  105. END;
  106. END Show;
  107. END BenchInterrupts.
  108. System.Free BenchInterrupts ~
  109. BenchInterrupts.Bench 1000000 ~
  110. BenchInterrupts.Show 2000 ~