Timer object
Timer object to simplify the routine task of capturing start and end times and displaying formatted results. Includes "stop", "resume", "restart", "elapsed" and "show" methods.
-- timer object to simplify routine task of capturing start and end times and -- displaying formatted results, e.g: -- mytimer.show('Elapsed so far'); -- might give -- +0 00:00:05.15 Elapsed so far -- -- Elapsed time is displayed as a constrained INTERVAL DAY(1) TO SECOND(2), which Oracle displays as -- +[days] [hh]:[mi]:[ss.xx] (where 'xx' represents two decimal places) -- -- Description is displayed by show() and can be set at any point i.e. via initialisation, -- restart(), stop(), resume() or show(). -- -- William Robertson 22 Feb 2004, www.williamrobertson.net -- -- 2004 02 29 Added resume() method and DBMS_APPLICATION_INFO calls. define day_precision = 1 define second_precision = 2 create or replace type timer as object ( start_time timestamp , end_time timestamp , description varchar2(1000) , status varchar2(7) , last_resumed_time timestamp , accumulated interval day to second , constructor function timer ( p_description varchar2 default null ) return self as result , member procedure restart -- Reset start time to now ( p_description varchar2 default null ) , member procedure stop -- Set stop time to now ( p_description varchar2 default null ) , member procedure resume -- Reset status to started: undoes stop without erasing start_time ( p_description varchar2 default null ) , member function elapsed -- Return elapsed time as interval value return interval day to second , member procedure show -- Display elapsed time with message ( p_description varchar2 default null ) , static function version -- Code repository version return varchar2 ) not final / show errors grant execute on timer to public; create or replace public synonym timer for timer; create or replace type body timer as constructor function timer ( p_description varchar2 default null ) return self as result is begin -- Restart() method reinitializes the timer (see below): restart(p_description); return; end; member procedure restart ( p_description varchar2 default null ) is begin self.resume(p_description); self.start_time := systimestamp; self.last_resumed_time := null; self.accumulated := null; self.status := 'RUNNING'; if p_description is not null then self.description := p_description; dbms_application_info.set_action(p_description); end if; end restart; -- Return the amount of time elapsed since either START_TIME or LAST_RESUMED_TIME. -- If there is an ACCUMULATED interval, add that as well (timing was stopped and later resumed: -- the elapsed time is stored as ACCUMULATED at the stop() event to allow it for a subsequent resume()). member function elapsed return interval day to second is -- Capture time-sensitive information first: k_end_time constant timestamp := systimestamp; k_start_time constant timestamp := case when self.last_resumed_time is not null then greatest(self.last_resumed_time,self.start_time) else self.start_time end; k_base_elapsed constant interval day to second := k_end_time - k_start_time; begin if self.status = 'STOPPED' then -- Clock has stopped: accumulated value will not change until timing is resumed: return self.accumulated; else return (k_end_time - k_start_time) + nvl(self.accumulated, interval '0' second); end if; end elapsed; -- Stop timer and calculate accumulated time. -- Amend description, if specified. -- Timer can later be restarted, or non-destructively resumed. member procedure stop ( p_description varchar2 default null ) is k_elapsed constant interval day to second := self.elapsed(); begin -- Check that timer has not already stopped: -- If so, ignore this call except to change description. if self.status = 'STOPPED' then null; else self.end_time := systimestamp; self.accumulated := k_elapsed; self.status := 'STOPPED'; end if; if p_description is not null then self.description := p_description; end if; end stop; member procedure resume ( p_description varchar2 default null ) is begin self.last_resumed_time := systimestamp; self.status := 'RUNNING'; if p_description is not null then self.description := p_description; dbms_application_info.set_action(p_description); end if; end resume; member procedure show ( p_description varchar2 default null ) is k_elapsed constant interval day(&&day_precision) to second(&&second_precision) := self.elapsed(); begin if p_description is not null then self.description := p_description; end if; dbms_output.put_line(k_elapsed || ' ' || self.description); end show; static function version return varchar2 is begin return '1.1'; end version; end; / show errors set doc off pro Demo using timer type: set echo on serverout on size 1000000 format wrapped declare k_iterations constant pls_integer := 4; v_interval interval day(&day_precision) to second(&second_precision); v_overall_timer timer := new timer('Overall time for demo'); v_split_timer timer := new timer('Add times for two events using stop and resume methods'); v_loop_timer timer := new timer('Loop with ' || k_iterations || ' iterations'); v_detail_timer timer := new timer(); begin dbms_output.put_line('...demo pausing 1 second...'); dbms_lock.sleep(1); v_split_timer.stop(); v_split_timer.show('v_split_timer stopped'); dbms_output.new_line(); dbms_lock.sleep(1); for i in 1..k_iterations loop v_detail_timer.restart('Loop iteration #' || i); dbms_lock.sleep(1); v_detail_timer.stop(); v_detail_timer.show(); -- Can specify message on NEW, restart or show v_overall_timer.show('running time so far'); end loop; dbms_output.new_line(); v_loop_timer.show(); dbms_output.new_line(); v_split_timer.resume(); v_split_timer.show('v_split_timer resumed after the loop.'); dbms_output.new_line(); dbms_output.put_line('...demo pausing 1 second...'); dbms_lock.sleep(1); v_interval := v_detail_timer.elapsed(); dbms_output.put_line ( chr(10)|| 'Captured time of last loop iteration "' || v_detail_timer.description || '": ' || v_interval ); dbms_output.new_line(); dbms_output.put_line('...demo pausing 1 second...'); dbms_output.new_line(); v_split_timer.show('v_split_timer resumed timing from where it left off.'); v_overall_timer.show('Entire demo'); end; / set echo off