[Back to TIMING SWAG index] [Back to Main SWAG index] [Original]

     {$G+,S-,R-,Q-}
     program timer;

     { Program to time short segments of code; inspired by Michael Abrash's
       Zen timer.  Donated to the public domain by D.J. Murdoch }

     uses
       opdos; { Object Professional unit, needed only for TimeMS,
                a millisecond timer. }

     const
       onetick = 1/33E6;  { This is the time in seconds for one cpu cycle.
                            I've got it set for a 33 Mhz machine. }

     { Instructions:  put your code fragment into a short routine called Segment.
       It should leave the stack unchanged, or it'll blow up when we clone it.
       It *must* have a far return at the end.  Play around with declaring it
       as an assembler procedure or not to see the cost of the TP entry and
       exit code. }

     { This example is Sean Palmer's "var2 := var1 div 2" replacement fragment. }

     var
       var1,var2 : integer;

     procedure Segment; far; assembler;
     asm
        mov ax,var1
        sar ax,1
        jns @S
        adc ax,0
      @S:
        mov var2,ax
     end;

     { This is the comparison TP code.  Note that it includes entry/exit code;
       play around with variations on the assembler version to make it a fair
       comparison }
     (*
     procedure Segment; far;
     begin
       var2 := var1 div 2;
     end;
     *)

     { This procedure is essential!!! Do not move it. It must follow
       Segment directly. }
     procedure Stop;
     begin
     end;

     { This routine will only be called once at the beginning of the program;
       set up any variables that Segment needs }

     procedure Setup;
     begin
       var1 := 5;
       writeln('This run, var1=',var1);
     end;

     const
       maxsize=65520;
       RETF   = $CB;
     var
       p : pointer;
       src,dest : ^byte;
       size : word;
       repeats : word;
       i : word;
       start,finish : longint;
       count : longint;
       main,overhead,millisecs : real;
     begin

       setup;

       { Get a segment of memory, and fill it up with as many copies
         of the segment as possible }

       size := ofs(stop) - ofs(Segment) -1;
       repeats := maxsize div size;
       getmem(p, size*repeats + 1);
       src := @Segment;
       dest := p;
       for i:=1 to repeats do
       begin
         move(src^,dest^,size);
         inc(dest,size);
       end;
       { Add a final RETF at the end. }
       dest^ := RETF;

       { Now do the timing.  Keep repeating one second loops indefinitely. }

       writeln(' Bytes     Clocks       ns       MIPS');
       repeat
         { First loop:  one second worth of calls to the segment }
         start := timems;
         count := 0;
         repeat
           asm
             call dword ptr p
           end;
           finish := timems;
           inc(count);
         until finish > 1000+start;
         main := (finish - start)/repeats/count;

         { Second loop:  1/2 second worth of calls to the RETF }
         start := timems;
         count := 0;
         repeat
           asm
             call dword ptr dest
           end;
           finish := timems;
           inc(count);
         until finish > 500+start;
         overhead := (finish-start)/count;
         millisecs := (main-overhead/repeats);
         writeln(size:6,millisecs/1000/onetick:11:1,
                        1.e6*millisecs:11:0,
                        1/millisecs/1000:11:3);
       until false;
     end.

    --- Msg V3.2
     * Origin: Murdoch's Point, Kingston, Ont, Canada  - -   (1:249/99.5)

[Back to TIMING SWAG index] [Back to Main SWAG index] [Original]