------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 199x by International Computer Science Institute            --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  is distributed  in the  hope that it will  be  useful, but --
-- WITHOUT ANY WARRANTY without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------

class TIME is
   -- Portable routines associated with timing. For finer grained timing,
   -- but possibly non-portable  timing consider using TIMES.
   -- Also note that this is a shared, non-reentratnt module
   -- 
   -- ANSI C provides very limited support for times, in particular
   -- makes it difficult to get at high resolution timers in a
   -- portable way.  For the moment, only the ANSI routines are used,
   -- but in the future more support will be nice.
   -- 
   -- I avoid using the ANSI clock() because it trivially rolls over
   -- when measured in microseconds, as happens on suns.  It also
   -- measures the processor time including child processes, which is
   -- somewhat ambiguous with a parallel make utility like the
   -- compiler uses.
   -- 
   -- Usage:  
   --     s ::= TIME::start;
   --     ... do something
   --     #OUT+TIME::elapsed;
   --     TIME::start;
   --     ... do something else
   --     #OUT+TIME::elapsed;  -- and so on
   
    private shared time_at_start:FLTD;

    seconds:FLTD is 
	-- Seconds since 00:00:00 UTC, January 1, 1970.  Precision is
        -- not guaranteed beyond seconds.  Built-in.
	builtin TIME_SECONDS;
    end;

    start is
	-- Begin timing. 
	time_at_start:=seconds;
    end;

    elapsed:FLTD is
	-- Return time since calling "start". Precision is not
	-- guaranteed beyond seconds.
	return seconds - time_at_start;
    end;
end;
---------------------------------------------------------------------
class TIMES is
   -- Return system, user and wall time in clock ticks
   -- This routines are not portable and may return different values
   -- on different systems. use at your own risc
   --   In regular programs that don't call "system" or "fork", 
   --   the child_sys_times are not useful.
   -- 
   --   In all programs, the user and system times include the times of
   --    all threads on  that particular cluster.  Hence, in an ideal
   --    pSather program running on a multi-processor machine, 
   --    the user and system times should be larger than the wall time, since
   --    the time used on each processor is added in.
   -- 
   --    Example usage:
   --        s: TIMES := #; -- Sets it to the current time (calls now)
   --        .... do something
   --        elapsed_time: TIMES := s.elapsed;
   --        #OUT + elapsed_time.wall_time.str;  -- Prints out the elapsed time

   readonly attr sys_time: INT;  
   -- Time in system calls (for the current cluster, in the case of pSather)
   
   readonly attr user_time: INT;
   -- Time for user code.  Behaves similarly to sys_time
   
   readonly attr child_sys_time: INT;
   -- Returns the system time for all children that have been 
   -- "system"ed or "fork"ed. i.e. the unix fork, not the pSather fork.
   -- Not useful for pSather
   
   readonly attr child_user_time: INT;
   -- Similar to child_sys_time, but for user code
   
   readonly attr wall_time: INT;
   -- Wall time in clock ticks.

   create:SAME is r::=new;r.now;return r; end;

   now is builtin TIMES_NOW; end;
   clk:INT is builtin TIMES_CLK; end;

   start is now; end;
   -- to measure the time used during some parts of the program,
   -- use start and elapsed. 

   elapsed:TIMES is return #TIMES-self; end;
   -- Elapsed returns the time since the last start.

   plus(a:SAME):SAME is
      -- Add two times
      n:TIMES:=#;
      n.sys_time:=sys_time+a.sys_time;
      n.user_time:=user_time+a.user_time;
      n.wall_time:=wall_time+a.wall_time;
      n.child_sys_time:=sys_time+a.child_sys_time;
      n.child_user_time:=user_time+a.child_user_time;
      return n;
   end;

   minus(a:SAME):SAME is
      -- Subtract two times
      n:TIMES:=#;
      n.sys_time:=sys_time-a.sys_time;
      n.user_time:=user_time-a.user_time;
      n.wall_time:=wall_time-a.wall_time;
      n.child_sys_time:=sys_time-a.child_sys_time;
      n.child_user_time:=user_time-a.child_user_time;
      return n;
   end;

   str:STR is
      -- standard way to print the time
      r::="";
      r:=r.append("wall time:        ",#FMT("<#.##>",(wall_time.flt/clk.flt)).str," sec.\n");
      r:=r.append("user time:        ",#FMT("<#.##>",(user_time.flt/clk.flt)).str," sec.\n");
      r:=r.append("system time:      ",#FMT("<#.##>",(sys_time.flt/clk.flt)).str," sec.\n");
      r:=r.append("user+system time: ",#FMT("<#.##>",((user_time+sys_time).flt/clk.flt)).str," sec.\n");
      r:=r.append("CPU usage:        ",((user_time+sys_time).flt*100.0/wall_time.flt).truncate.str," %\n");
      return r;
   end;
end;
-----------------------------------------------------------------------------
class MEMORY_USAGE is
   -- returns the number of bytes currently in either the heap or
   -- in use by the garbage collector. Highly non portable.
   -- The linking step will break if this class is used on
   -- a system it is not supported. The usage of the class is
   -- similar to the TIMES above.

   readonly attr sbrk_size: INT;
   readonly attr gc_size:INT;

   create:SAME is r::=new;r.now;return r; end;

   now is builtin MEMORY_NOW; end;


   start is now; end;
   elapsed:SAME is return #SAME-self; end;
   -- to measure the memory used during some parts of the program,
   -- use start and elapsed. Elapsed returns the memory since the last
   -- start.
   
   plus(a:SAME):SAME is
      n:SAME:=#;
      n.sbrk_size:=sbrk_size+a.sbrk_size;
      n.gc_size:=gc_size+a.gc_size;
      return n;
   end;

   minus(a:SAME):SAME is
      n:SAME:=#;
      n.sbrk_size:=sbrk_size-a.sbrk_size;
      n.gc_size:=gc_size-a.gc_size;
      return n;
   end;

   -- standard way to print the time
   str:STR is
      r::="";
      r:=r.append("sbrk size: ",#FMT("<#########>",sbrk_size).str," Bytes\n");
      r:=r.append("GC size:   ",#FMT("<#########>",gc_size).str," Bytes\n");
      return r;
   end;
end;


-- vim:sw=3:nosmartindent
