home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2 / PcPro-2a.iso / Demos / ProDelph / PROTMAIN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  2000-01-05  |  16.3 KB  |  632 lines

  1. //PROFILE-NO
  2. unit protmain;
  3. {$O-}  // Do not remove! Delphi might crash !!!!
  4. {$R-}
  5. {$Q-}
  6. {$A+}
  7.  
  8. interface
  9.  
  10. uses
  11.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  12.   ExtCtrls, StdCtrls;
  13.  
  14. TYPE
  15. {$IFDEF VER120 }
  16.   TMyComp  = Int64;
  17. {$ELSE }
  18.   {$IFDEF VER130 }
  19.     TMyComp  = Int64;
  20.   {$ELSE }
  21.     TMyComp  = Comp;
  22.   {$ENDIF }
  23. {$ENDIF }
  24.   TMyLargeInteger = RECORD
  25.                     CASE Byte OF
  26.                      0 : ( LowPart  : DWORD; HighPart : LongInt );
  27.                      1 : ( QuadPart : TMyComp );
  28.                   END;
  29.  
  30. type
  31.   TForm1 = class(TForm)
  32.     Button1: TButton;
  33.     Label1: TLabel;
  34.     Label2: TLabel;
  35.     Label3: TLabel;
  36.     Label4: TLabel;
  37.     Label5: TLabel;
  38.     Label6: TLabel;
  39.     Label7: TLabel;
  40.     f0: TLabel;
  41.     f0d: TLabel;
  42.     f10: TLabel;
  43.     f10d: TLabel;
  44.     f100: TLabel;
  45.     f1000: TLabel;
  46.     f10000: TLabel;
  47.     f100d: TLabel;
  48.     f1000d: TLabel;
  49.     f10000d: TLabel;
  50.     Bevel1: TBevel;
  51.     Label18: TLabel;
  52.     Label19: TLabel;
  53.     Label20: TLabel;
  54.     pmam: TLabel;
  55.     prom: TLabel;
  56.     pmamd: TLabel;
  57.     promd: TLabel;
  58.     Label25: TLabel;
  59.     Label26: TLabel;
  60.     Bevel2: TBevel;
  61.     Bevel3: TBevel;
  62.     Bevel4: TBevel;
  63.     Bevel5: TBevel;
  64.     Bevel6: TBevel;
  65.     Bevel7: TBevel;
  66.     Bevel8: TBevel;
  67.     Bevel9: TBevel;
  68.     Bevel10: TBevel;
  69.     Bevel11: TBevel;
  70.     Label8: TLabel;
  71.     Bevel12: TBevel;
  72.     tmlf: TLabel;
  73.     tmlfd: TLabel;
  74.     Label9: TLabel;
  75.     Label10: TLabel;
  76.     Label11: TLabel;
  77.     Label12: TLabel;
  78.     Label13: TLabel;
  79.     Label14: TLabel;
  80.     Label15: TLabel;
  81.     Label16: TLabel;
  82.     Label17: TLabel;
  83.     Label21: TLabel;
  84.     Bevel13: TBevel;
  85.     recu: TLabel;
  86.     recud: TLabel;
  87.     Label24: TLabel;
  88.     Label22: TLabel;
  89.     Label23: TLabel;
  90.     procedure StartItAll(Sender: TObject);
  91.   private
  92.     { Private-Deklarationen }
  93.     PROCEDURE UserMessage ( VAR Message ); Message WM_USER+5;
  94.     FUNCTION  PostIt : TMyLargeInteger;
  95.   public
  96.     { Public-Deklarationen }
  97.   end;
  98.  
  99. var
  100.   Form1: TForm1;
  101.  
  102. implementation
  103.  
  104. {$R *.DFM}
  105.  
  106. CONST
  107.   MHZ1 = 0; MHZn = 28;
  108.   MHzTab : Array[MHZ1..MHZn] OF Word =
  109.           (33, 40, 50, 66, 75, 83, 90, 100, 120, 133, 150, 166, 180, 200, 233,
  110.            266, 300, 333, 350, 366, 380, 400, 433, 450, 466, 500, 533, 550, 600 );
  111.  
  112. VAR
  113.   MHZes  : Double;
  114.   QPCAss : TMyLargeInteger; // Time used for PRTSC + mov + mov
  115.  
  116. PROCEDURE EstimateMHz ;
  117. VAR
  118.   mega         : Double;
  119.   takte        : TMyLargeInteger;
  120.   dauer        : TMyLargeInteger;
  121.   i            : Integer;
  122.   tickx        : LongInt;
  123.   tick1, tick2 : LongInt;
  124.   startt, endt : TMyLargeInteger;
  125. BEGIN
  126.   startt.QuadPart := 0;
  127.   dauer.quadpart  := 0;
  128.   tick1 := GetTickCount;
  129.   REPEAT
  130.     tick2 := GetTickCount;
  131.   UNTIL tick2 <> tick1;
  132.  
  133.   REPEAT
  134.     tick1 := GetTickCount;
  135.   UNTIL tick2 <> tick1;
  136.  
  137.   asm
  138.     DW 310FH;
  139.     mov startt.lowpart,eax
  140.     mov startt.highpart,edx
  141.   end;
  142.   tickx := tick1;
  143.  
  144.   FOR i := 1 TO 66 DO BEGIN
  145.     tick2 := tick1;
  146.     REPEAT
  147.       tick1 := GetTickCount;
  148.     UNTIL tick1 <> tick2;
  149.   END;
  150.   asm
  151.     DW 310FH;
  152.     mov endt.lowpart,eax
  153.     mov endt.highpart,edx
  154.   end;
  155.  
  156.   dauer.lowpart  := tick1 - tickx ;
  157.   takte.quadpart := endt.quadpart - startt.quadpart - QPCAss.QuadPart - QPCAss.QuadPart;
  158.   mega := takte.quadpart;
  159.   mega := mega / dauer.lowpart / 1000;
  160.   MHZes := Trunc(mega);
  161.  
  162.   FOR i := MHZ1 TO MHZn DO BEGIN
  163.     IF Abs(MHZes - MHZTab[i]) < 5 THEN BEGIN
  164.       MHZes := MHZTab[i];
  165.       break;
  166.     END;
  167.   END;
  168. END;
  169.  
  170. PROCEDURE ConvertTime ( VAR wertstr : String; wert : Double; AsCycles : Boolean );
  171. VAR
  172.   einheit : String;
  173. BEGIN
  174.   IF AsCycles = TRUE THEN BEGIN
  175.     Str(wert:0:0, einheit);
  176.     wertstr := '';
  177.     WHILE Length(einheit) > 3 DO BEGIN
  178.       wertstr := ',' + Copy(einheit, Length(einheit)-2, 3) + wertstr;
  179.       einheit := Copy(einheit, 1, Length(einheit)-3);
  180.     END;
  181.     wertstr := einheit + wertstr;
  182.     exit;
  183.   END;
  184.   wert := wert / MHZes;
  185.   IF wert < 1000.0 THEN BEGIN       { < 1 ms -> micro sec}
  186.     einheit := ' ╡S';
  187.     END
  188.   ELSE BEGIN
  189.     IF wert < 1000000.0 THEN BEGIN  { < 1 sec -> milli sec }
  190.       wert := wert / 1000;
  191.       einheit := ' ms';
  192.       END
  193.     ELSE BEGIN
  194.       wert := wert / 1000000.0;     { nano sec -> sec }
  195.       IF wert < 60.0 THEN BEGIN
  196.         einheit := '  s ';
  197.         END
  198.       ELSE BEGIN
  199.         wert := wert / 60.0;        { sec -> min }
  200.         einheit := '  m ';
  201.         IF wert > 60 THEN BEGIN
  202.           wert := wert / 60.0;      { min -> std }
  203.           einheit := '  h ';
  204.         END;
  205.       END;
  206.     END;
  207.   END;
  208.   Str(wert:0:3, wertstr);
  209.   wertstr := wertstr + einheit;
  210. END;
  211.  
  212. FUNCTION MidFunction  : Integer; Forward;
  213. FUNCTION DeepFunction  : Integer; Forward;
  214.  
  215. VAR
  216.   res     : Array[0..10] OF TMyLargeInteger;
  217.   ta      : TMyLargeInteger;
  218.   tsum    : TMyLargeInteger;
  219.   count   : Integer;
  220.   resstr  : Array[0..10] OF String;
  221.   resstr2 : Array[0..10] OF String;
  222.  
  223.  
  224. PROCEDURE TForm1.UserMessage ( VAR Message );
  225. VAR
  226.   i : Integer;
  227. BEGIN
  228.   asm
  229.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  230.     mov ta.lowpart,eax
  231.     mov ta.highpart,edx
  232.   end;
  233.  
  234.   FOR i := 1 TO 1000 DO
  235.     INC(count);
  236.  
  237.   asm
  238.     DW 310FH;   // get cycles after tested instructions
  239.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  240.     sub eax,ta.lowpart
  241.     sbb edx,ta.highpart
  242.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  243.     sub eax,QPCAss.lowpart
  244.     sbb edx,QPCAss.highpart
  245.     // = No of cycles for the measured instructions
  246.     // stored in tsum
  247.     mov tsum.lowpart,eax
  248.     mov tsum.highpart,edx
  249.   end;
  250.   res[7].lowpart := res[7].lowpart + tsum.lowpart;
  251. END;
  252.  
  253. FUNCTION TForm1.PostIt : TMyLargeInteger;
  254. BEGIN
  255.   asm
  256.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  257.     mov ta.lowpart,eax
  258.     mov ta.highpart,edx
  259.   end;
  260.   Result.lowpart  := 0;
  261.   Result.highpart := 0;
  262.  
  263.   PostMessage(application.mainform.handle, WM_USER+5, 1, 2);
  264. // In the program protest2 you will find here Application.ProcessMessages, it is
  265. // here at the end of the procedure, in order not to be measured. A good rofiler
  266. // stops measuring before entering that procedure. The reason is, that the
  267. // current process, so to say, hands over the cpu to another process. E.g. that
  268. // the current process is interrupted and contiued after returning from
  269. // Application.ProcessMessages. That's why this procedure shouldn't be measured.
  270. // Even Windows does not change to another process but continues the current one,
  271. // which will be done in this example because we just posted a message to the
  272. // main window, measurement must be stopped. The next executed procedure, in this
  273. // example UserMessage or the default handler, is NOT a child procedure of this.
  274.   asm
  275.     DW 310FH;   // get cycles after tested instructions
  276.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  277.     sub eax,ta.lowpart
  278.     sbb edx,ta.highpart
  279.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  280.     sub eax,QPCAss.lowpart
  281.     sbb edx,QPCAss.highpart
  282.     // = No of cycles for the measured instructions
  283.     // stored in tsum
  284.     mov tsum.lowpart,eax
  285.     mov tsum.highpart,edx
  286.   end;
  287.   result.lowpart := tsum.lowpart;
  288.   Application.ProcessMessages;
  289. END;
  290.  
  291. FUNCTION Minimum ( a, b : TMyComp ) : TMyComp;
  292. BEGIN
  293.   IF a > b THEN
  294.     Result := b
  295.   ELSE
  296.     Result := a;
  297. END;
  298.  
  299. FUNCTION GetAssemblerQPC : TMyLargeInteger;
  300. VAR
  301.   n  : Integer;
  302.   te : TMyLargeInteger;
  303.   ts : TMyLargeInteger;
  304. BEGIN
  305.   Result.quadpart := 1000000000;
  306.   FOR n := 1 TO 40 DO BEGIN
  307.     // Until here a certain amount of instructions have been processed
  308.     // The next instruction (PRTSC) gives how many
  309.     asm
  310.       DW 310FH;
  311.       mov ts.lowpart,eax
  312.       mov ts.highpart,edx
  313.       // The next line results in how many cycles were used until here
  314.       // ts - te : how many cycles were used by the previous 3 instruction or
  315.       // by the next 3
  316.       DW 310FH;
  317.       mov te.lowpart,eax
  318.       mov te.highpart,edx
  319.     end;
  320.     Result.quadpart := Minimum(Result.quadpart, ABS(te.Quadpart - ts.QuadPart));
  321.   END;
  322. END;
  323.  
  324. FUNCTION FunctionWith10( VAR index : Integer ) : TMyLargeInteger;
  325. VAR
  326.   i : Integer;
  327. BEGIN
  328.   asm
  329.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  330.     mov ta.lowpart,eax
  331.     mov ta.highpart,edx
  332.   end;
  333.   Result.lowpart  := 0;
  334.   Result.highpart := 0;
  335.  
  336.   FOR i := 1 TO 10 DO
  337.     INC(Index);
  338.   asm
  339.     DW 310FH;   // get cycles after tested instructions
  340.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  341.     sub eax,ta.lowpart
  342.     sbb edx,ta.highpart
  343.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  344.     sub eax,QPCAss.lowpart
  345.     sbb edx,QPCAss.highpart
  346.     // = No of cycles for the measured instructions
  347.     // stored in tsum
  348.     mov tsum.lowpart,eax
  349.     mov tsum.highpart,edx
  350.   end;
  351.   result.lowpart := tsum.lowpart;
  352. END;
  353.  
  354. FUNCTION FunctionWith100( VAR index : Integer ) : TMyLargeInteger;
  355. VAR
  356.   i : Integer;
  357. BEGIN
  358.   asm
  359.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  360.     mov ta.lowpart,eax
  361.     mov ta.highpart,edx
  362.   end;
  363.   Result.lowpart  := 0;
  364.   Result.highpart := 0;
  365.  
  366.   FOR i := 1 TO 100 DO
  367.     INC(Index);
  368.  
  369.   asm
  370.     DW 310FH;   // get cycles after tested instructions
  371.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  372.     sub eax,ta.lowpart
  373.     sbb edx,ta.highpart
  374.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  375.     sub eax,QPCAss.lowpart
  376.     sbb edx,QPCAss.highpart
  377.     // = No of cycles for the measured instructions
  378.     // stored in tsum
  379.     mov tsum.lowpart,eax
  380.     mov tsum.highpart,edx
  381.   end;
  382.   result.lowpart := tsum.lowpart;
  383. END;
  384.  
  385. FUNCTION FunctionWith1000( VAR index : Integer ) : TMyLargeInteger;
  386. VAR
  387.   i : Integer;
  388. BEGIN
  389.   asm
  390.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  391.     mov ta.lowpart,eax
  392.     mov ta.highpart,edx
  393.   end;
  394.   Result.lowpart  := 0;
  395.   Result.highpart := 0;
  396.  
  397.   FOR i := 1 TO 1000 DO
  398.     INC(Index);
  399.  
  400.   asm
  401.     DW 310FH;   // get cycles after tested instructions
  402.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  403.     sub eax,ta.lowpart
  404.     sbb edx,ta.highpart
  405.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  406.     sub eax,QPCAss.lowpart
  407.     sbb edx,QPCAss.highpart
  408.     // = No of cycles for the measured instructions
  409.     // stored in tsum
  410.     mov tsum.lowpart,eax
  411.     mov tsum.highpart,edx
  412.   end;
  413.   result.lowpart := tsum.lowpart;
  414. END;
  415.  
  416. FUNCTION FunctionWith10000( VAR index : Integer ) : TMyLargeInteger;
  417. VAR
  418.   i : Integer;
  419. BEGIN
  420.   asm
  421.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  422.     mov ta.lowpart,eax
  423.     mov ta.highpart,edx
  424.   end;
  425.   Result.lowpart  := 0;
  426.   Result.highpart := 0;
  427.  
  428.   FOR i := 1 TO 10000 DO
  429.     INC(index);
  430.  
  431.   asm
  432.     DW 310FH;   // get cycles after tested instructions
  433.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  434.     sub eax,ta.lowpart
  435.     sbb edx,ta.highpart
  436.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  437.     sub eax,QPCAss.lowpart
  438.     sbb edx,QPCAss.highpart
  439.     // = No of cycles for the measured instructions
  440.     // stored in tsum
  441.     mov tsum.lowpart,eax
  442.     mov tsum.highpart,edx
  443.   end;
  444.   result.lowpart := tsum.lowpart;
  445. END;
  446.  
  447. FUNCTION TopFunction ( VAR index : Integer ) : TMyLargeInteger;
  448. VAR
  449.   i : Integer;
  450. BEGIN
  451.   asm
  452.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  453.     mov ta.lowpart,eax
  454.     mov ta.highpart,edx
  455.   end;
  456.  
  457.   FOR i := 1 TO 10 DO
  458.     index := MidFunction;
  459.   Result.highpart := 0;
  460.   Result.lowpart := 0;
  461.  
  462.   asm
  463.     DW 310FH;   // get cycles after tested instructions
  464.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  465.     sub eax,ta.lowpart
  466.     sbb edx,ta.highpart
  467.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  468.     sub eax,QPCAss.lowpart
  469.     sbb edx,QPCAss.highpart
  470.     // = No of cycles for the measured instructions
  471.     // stored in tsum
  472.     mov tsum.lowpart,eax
  473.     mov tsum.highpart,edx
  474.   end;
  475.   result.lowpart := tsum.lowpart;
  476. END;
  477.  
  478. FUNCTION MidFunction  : Integer;
  479. VAR
  480.   i : Integer;
  481. BEGIN
  482.   FOR i := 1 TO 10 DO
  483.     Result := DeepFunction;
  484. END;
  485.  
  486. FUNCTION DeepFunction : Integer;
  487. BEGIN
  488.   Result := 0;
  489. END;
  490.  
  491. FUNCTION DoRecursion ( VAR HowOften : Integer ) : DWORD;
  492. BEGIN
  493.   DEC(HowOften);
  494.   IF HowOften <= 0 THEN BEGIN
  495.     Result := 0;
  496.     exit;
  497.   END;
  498.   result := DoRecursion(HowOften);
  499. END;
  500.  
  501. FUNCTION HeaderTime ( VAR HowOften : Integer ) : TMyLargeInteger;
  502. BEGIN
  503. END;
  504.  
  505. FUNCTION Recursion( VAR index : Integer ) : DWORD;
  506. VAR
  507.   i : Integer;
  508.   h : TMyLargeInteger;
  509. BEGIN
  510. // Calculate how many cycles a function header uses. The measurement normally
  511. // only measures the body of a function. This procedure measures one additional
  512. // function header. So we must subtract the time for this.
  513.   FOR i := 1 TO 40 DO
  514.     HeaderTime(index);
  515.   asm
  516.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  517.     mov ta.lowpart,eax
  518.     mov ta.highpart,edx
  519.   end;
  520.   HeaderTime(index);
  521.   asm
  522.     DW 310FH;   // get cycles after tested instructions
  523.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  524.     sub eax,ta.lowpart
  525.     sbb edx,ta.highpart
  526.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  527.     sub eax,QPCAss.lowpart
  528.     sbb edx,QPCAss.highpart
  529.     // = No of cycles for the measured instructions
  530.     // stored in tsum
  531.     mov h.lowpart,eax
  532.     mov h.highpart,edx
  533.   end;
  534. // Now we make the test for the recursive function
  535.   asm
  536.     DW 310FH;   // first PRTSC, get cycles before tested instruction
  537.     mov ta.lowpart,eax
  538.     mov ta.highpart,edx
  539.   end;
  540.  
  541.   DoRecursion(index);
  542.  
  543.   asm
  544.     DW 310FH;   // get cycles after tested instructions
  545.     // Next lines calculate the no of cycles now - no of cycles before first PRTSC
  546.     sub eax,ta.lowpart
  547.     sbb edx,ta.highpart
  548.     // Next lines subtract no of cycles for the first PRTSC + mov instructions
  549.     sub eax,QPCAss.lowpart
  550.     sbb edx,QPCAss.highpart
  551.     // Next lines subtract no of cycles for additional function header
  552.     sub eax,h.lowpart
  553.     sbb edx,h.highpart
  554.     // = No of cycles for the measured instructions
  555.     // stored in tsum
  556.     mov tsum.lowpart,eax
  557.     mov tsum.highpart,edx
  558.   end;
  559.   result := tsum.lowpart;
  560. END;
  561.  
  562. procedure TForm1.StartItAll(Sender: TObject);
  563. VAR
  564.   i, x     : Integer;
  565.   xd       : Double;
  566.   Ergebnis : Integer;
  567. begin
  568.  
  569.   EstimateMHZ;
  570.  
  571.   QPCAss  := GetAssemblerQPC;
  572.   FOR i := 0 TO 10 DO
  573.     res[i].quadpart := 0;
  574.  
  575.   Ergebnis := 0;
  576.   FOR i := 1 TO 200 DO
  577.     res[5].lowpart := res[5].lowpart + TopFunction(Ergebnis).lowpart;
  578.   Ergebnis := 0;
  579.   FOR i := 1 TO 200 DO
  580.     res[4].lowpart := res[4].lowpart + FunctionWith10000(Ergebnis).lowpart;
  581.   Ergebnis := 0;
  582.   FOR i := 1 TO 200 DO
  583.     res[3].lowpart := res[3].lowpart + FunctionWith1000(Ergebnis).lowpart;
  584.   Ergebnis := 0;
  585.   FOR i := 1 TO 200 DO
  586.     res[2].lowpart := res[2].lowpart + FunctionWith100(Ergebnis).lowpart;
  587.   Ergebnis := 0;
  588.   FOR i := 1 TO 200 DO
  589.     res[1].lowpart := res[1].lowpart + FunctionWith10(Ergebnis).lowpart;
  590.   Ergebnis := 0;
  591.   FOR i := 1 TO 200 DO BEGIN
  592.     Ergebnis := 10;
  593.     res[8].lowpart := res[8].lowPart + Recursion(Ergebnis);
  594.   END;
  595.   Ergebnis := 0;
  596.   FOR i := 1 TO 200 DO BEGIN
  597.     count := 0;
  598.     res[6].lowpart := res[6].lowpart + PostIt.lowpart;
  599.   END;
  600.  
  601.   FOR i := 0 TO 10 DO BEGIN
  602.     x := res[i].lowpart;
  603.     IF (i <> 8) AND (i <> 5) THEN
  604.       x := x DIV 200;
  605.     ConvertTime(resstr[i], x, TRUE);
  606.     xd := Round(x);
  607.     ConvertTime(resstr2[i], xd, FALSE);
  608.   END;
  609.  
  610.   f0.caption  := '0';
  611.   f10.caption := resstr[1];
  612.   f100.caption := resstr[2];
  613.   f1000.caption := resstr[3];
  614.   f10000.caption := resstr[4];
  615.   tmlf.caption := resstr[5];
  616.   pmam.caption := resstr[6];
  617.   prom.caption := resstr[7];
  618.   recu.caption := resstr[8];
  619.  
  620.   f0d.caption  := '0.000 ╡S';
  621.   f10d.caption := resstr2[1];
  622.   f100d.caption := resstr2[2];
  623.   f1000d.caption := resstr2[3];
  624.   f10000d.caption := resstr2[4];
  625.   tmlfd.caption := resstr2[5];
  626.   pmamd.caption := resstr2[6];
  627.   promd.caption := resstr2[7];
  628.   recud.caption := resstr2[8];
  629. end;
  630.  
  631. end.
  632.