:TITLE: Leftovers - time, unset
;#
;# RCSID: $Header: /home/clif/CVS_ROOT/TclTutor/Tcl39.lsn,v 1.5 2000/04/24 16:17:53 clif Exp $
;# Copyright (c) 1995 Clif Flynt
;# 9300 Fleming Rd.
;# Dexter, MI  48130
;# clif@cflynt.com
;# See file "NOTICE" for licensing terms.
;#
:LESSON_TEXT_START_LEVEL 0:

The <B>time</B> command measures the length of time a proc or command
takes to run.  This is useful when you are optimizing a script. 
<P>
The unset command deletes a variable from the namespace.
<P>
<DL>
<B><DT>time</B> <I>script ?count?</I>
<DD>Returns the number of milliseconds it took to execute <I>script</I>.  If
<I>count</I> is specified, it will run the script <I>count</I> times, and
average the result.  The time is elapsed time, not CPU time.
<B><DT>unset</B> <I>variableName1 ?variableName2 ...?</I>
<DD>Deletes <I>variableName</I> from the interpreter's namespace.  If
<I>variableName</I> is an array name, then the entire array is deleted. 
If <I>variableName</I> is an element in an array, then only that element
is deleted.  If any of the variables to delete do not exist, then <B>unset</B>
will return an error, and any variables after the non-existent variable
will not be deleted.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 1:
The simplest method of making a script run faster is to buy a faster
processor.  Unfortunately, this isn't always an option.  You may need to
optimize your script to run faster.  This is difficult if you can't measure
the time it takes to run the portion of the script that you are trying to
optimize.
<P>
The <B>time</B> command is the solution to this problem.  <B>Time</B>
will measure the length of time that it takes to execute a script.  You
can then modify the script, rerun <B>time</B> and see how much you improved
it.
<P>
You may also need to optimize the memory used by a script, or perhaps clean
up variables after a each pass through a loop.  The <B>unset</B> command
will delete a variable from the interpreters namespace.
<P>
After you've run the example, 
play with the size of the loop counters in <B>timetst1</B> and <B>timetst2</B>.  If you make the inner loop counter
5 or less, it may take longer to execute <B>timetst2</B> than it takes for
<B>timetst1</B>.  This is because it takes time to calculate and assign the
variable <B>k</B>, and if the inner loop is too small, then the gain in not
doing the multiply inside the loop is lost in the time it takes to do the
outside the loop calculation.
<DL>
<B><DT>time</B> <I>script ?count?</I>
<DD>Returns the number of milliseconds it took to execute <I>script</I>.  If
<I>count</I> is specified, it will run the script <I>count</I> times, and
average the result.  The time is elapsed time, not CPU time.
<B><DT>unset</B> <I>variableName1 ?variableName2 ...?</I>
<DD>Deletes <I>variableName</I> from the interpreter's namespace.  If
<I>variableName</I> is an array name, then the entire array is deleted. 
If <I>variableName</I> is an element in an array, then only that element
is deleted.  If any of the variables to delete do not exist, then <B>unset</B>
will return an error, and any variables after the non-existent variable
will not be deleted.
</DL>
:TEXT_END:

:LESSON_TEXT_START_LEVEL 2:
One of the unwritten rules of computer programming is that no matter
how fast a program runs, it would be better if it ran faster.
<P>
The simplest method of making a script run faster is to buy a faster
processor.  Unfortunately, this isn't always an option.  You may need to
optimize your script to run faster.  This is difficult if you can't measure
the time it takes to run the portion of the script that you are trying to
optimize.
<P>
The <B>time</B> command is the solution to this problem.  <B>Time</B>
will measure the length of time that it takes to execute a script.  You
can then modify the script and rerun <B>time</B> to see how much you improved
it.
<P>
You may also need to optimize the memory used by a script, or perhaps clean
up variables after a each pass through a loop.  The <B>unset</B> command
will delete a variable from the interpreters namespace.
<P>
Run the example, and look at the output.  The two procs are identical, 
except that <B>timetst2</B> does a multiplication outside the <B>j</B>
loop.  Note the difference in the time it takes to perform each proc.
Moving calculations outside of a loop is one of the standard methods of
optimizing a program.
<P>
Play with the size of the loop counters.  If you make the inner loop counter
5 or less, it may take longer to execute <B>timetst2</B> than it takes for
<B>timetst1</B>.  This is because it takes time to calculate and assign the
variable <B>k</B>, and if the inner loop is too small, then the gain in not
doing the multiply inside the loop is lost in the time it takes to do the
outside the loop calculation.
<P>
The next several examples show how a variable can be unset.
<DL>
<B><DT>time</B> <I>script ?count?</I>
<DD>Returns the number of milliseconds it took to execute <I>script</I>.  If
<I>count</I> is specified, it will run the script <I>count</I> times, and
average the result.  The time is elapsed time, not CPU time.
<B><DT>unset</B> <I>variableName1 ?variableName2 ...?</I>
<DD>Deletes <I>variableName</I> from the interpreter's namespace.  If
<I>variableName</I> is an array name, then the entire array is deleted. 
If <I>variableName</I> is an element in an array, then only that element
is deleted.  If any of the variables to delete do not exist, then <B>unset</B>
will return an error, and any variables after the non-existent variable
will not be deleted.
</DL>
:TEXT_END:

:CODE_START:

;# Two procs to demonstrate using the time command for loop optimization

proc timetst1 {lst} {
  set x [lsearch $lst "5000"]
  return $x
  }

proc timetst2 {array} {
  upvar $array a
  return $a(5000);
  }

# Make a long list and a large array.

for {set i 0} {$i < 5001} {incr i} {
  set array($i) $i
  lappend list $i
}

;# Observe the difference in the time it takes to run each proc

puts "Time for list search: [ time {timetst1 $list} 10]"
puts "Time for array index: [ time {timetst2 array} 10]"

;# This proc tests for the existence of its argument, and
;#   prints out whether or not the variable exists.

proc existence {variable} {
  upvar $variable testVar;
  if {[info exists testVar]} {
    puts "$variable Exists"
    } else {
    puts "$variable Does Not Exist"
    }
  }

;# Set several variable for later testing and unsetting.

set x 1
set y 2
for {set i 0} {$i < 5} {incr i} {
  set a($i) $i;
  }

puts "\ntesting unsetting a simple variable"
   ;# Confirm that x exists.
existence x
   ;# Unset x
puts "x has been unset"
unset x
   ;# Confirm that x no longer exists.
existence x


;# Do the same for a(0);

puts "\ntesting unsetting a member of an array"
existence a(0);
puts "a0 has been unset"
unset a(0);
existence a(0);


puts "\ntesting unsetting several members of an array, with an error"
existence a(3);
existence a(4);
catch {unset a(3) a(0) a(4)}
puts "\nAfter attempting to delete a(3), a(0) and a(4)"
existence a(3);
existence a(4);

puts "\ntesting unsetting an array"
existence a;
puts "a has been unset"
unset a;
existence a;
:TEXT_END:

