home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / jed098-4.zip / JED / DOC / PROGRAM.TXT < prev    next >
Text File  |  1997-02-01  |  6KB  |  196 lines

  1. This document provides some tips for writing better and more efficient
  2. S-Lang code.  It is not meant to be a tutorial on S-Lang.
  3.  
  4. Writing Fast Routines
  5. =====================
  6.  
  7.   The first thing that one must realize is that S-Lang is an interpreted
  8.   language and runs much slower than a compiled language.  This fact can be
  9.   used to justify a rule of thumb that may be used to gauge the speed of a
  10.   S-Lang expression:
  11.  
  12.     Rule of Thumb: All single token intrinsic statements and expressions run
  13.            at the same speed.
  14.  
  15.   The phrase ``intrinsic statements and expressions'' includes not only
  16.   intrinsic functions but also assignment operations as well as pushing an
  17.   object on the stack.  For example, consider the expression:
  18.   
  19.      n = down (20);
  20.      
  21.    This expression consists of the operation of pushing `20' onto the stack
  22.    followed by calling the intrinsic function `down' and assigning it to
  23.    `n'.  It is easiest to see this using the RPN form:
  24.    
  25.    .  20 down =n
  26.    
  27.    (Remember, all RPN expressions must lie on lines that begin with a
  28.    period.).   From the above rule of thumb, this expression executes at a
  29.    speed of 3 units.
  30.    
  31.    Now consider something more tricky.  Consider the expression:
  32.    
  33.        n = n + 1;
  34.        
  35.    It also executes in 3 units of time.  This is equivalent to:
  36.    
  37.        n++;
  38.        
  39.    However, `n++' is a single token and executes in 1 unit of time!  So, the
  40.    rule is that one should try to use the `++' and `--' forms whenever
  41.    possible.  The same statement is true for the `+=' and `-=' operators.
  42.    The statement:
  43.    
  44.       n += 1;
  45.       
  46.    parses to two tokens:
  47.    
  48.    .  1 +=n;
  49.    
  50.    and executes in 2 units.  Note that 
  51.    
  52.       n++; n++;
  53.       
  54.    also achieves the effect `n = n + 2' but executes in 2 units as well.
  55.    
  56.        * Note:  These special forms are currently limited for integers and
  57.                 do not work with variables that represent floating point 
  58.         values.
  59.    
  60.    At this point, it should be clear that the code that executes the fastest
  61.    is the code that contains the least number of tokens.   However, this is
  62.    only partially true and only holds for expressions that do not call other
  63.    S-Lang functions.
  64.    
  65.    As an example, consider the recursive function below:
  66.    
  67.        define fib ();   % definition required for recursion
  68.        
  69.        define fib(n)
  70.        {
  71.           if (n == 0) return(0);
  72.           if (n == 1) return(1);
  73.   
  74.           return fib(n - 1) + fib(n - 2);
  75.        }
  76.        
  77.    The first thing to do is to change
  78.    
  79.          if (n == 0) return 0;
  80.      
  81.    to 
  82.          !if (n) return 0;
  83.      
  84.    since the expression `n == 0' executes in 3 units and `n' executes in
  85.    only 1.  Similarly, the statement:
  86.    
  87.          if (n == 1) return 1;
  88.      
  89.    may be written:
  90.    
  91.          n--; !if (n) return 1;
  92.   
  93.    with the side effect that n is reduced by 1 in the process.  But that is
  94.    a good thing because we can then modify:
  95.    
  96.        return fib (n - 1) + fib (n - 2);
  97.        
  98.    to:
  99.    
  100.        return fib(n) + fib (n - 1);
  101.        
  102.    Actually, we can do better than that.  We can write `n - 1' which
  103.    executes in 3 units to the equivalent expression `n--, n' that executes
  104.    in 2 units to produce:
  105.    
  106.       return fib (n) + fib (n--, n);
  107.       
  108.    Here the fact that `n--' does not affect the stack makes this possible.
  109.    Finally, we are left with:
  110.    
  111.       define fib (n)
  112.       {
  113.         !if (n) return 0;
  114.     n--; !if (n) return 1;
  115.     return fib(n) + fib (n--, n);
  116.       }
  117.  
  118.    Simply counting tokens (if, !if, fib, n, ==, 1, -, etc...) shows that the
  119.    unoptimized version has 19 whereas the optimized version has 12. Applying
  120.    the rule of thumb to this suggests that the optimized version should run
  121.    19/12 times faster!  The reader is encouraged to compare the speed of the
  122.    first version of `fib' with the optimized version to verify that this is
  123.    indeed the case (use something like fib(25)).
  124.    
  125.    Here is a brief summary of what to do to squeeze extra speed out of
  126.    S-Lang: 
  127.    
  128.       1.  Use the `++', `--', `+=', and `-=' forms wherever possible.
  129.       2.  Eliminate `if (something == 0)' in favor of `!if (something)'
  130.       3.  Avoid `while(1)' and use `forever' instead.
  131.       4.  For simple looping a fixed number of times use `loop'.
  132.       5.  If you have something like:
  133.       
  134.             for (i = imin; i <= imax; i += di) 
  135.           {
  136.              ...
  137.           }
  138.         
  139.       replace it by the MUCH faster and smaller version
  140.       
  141.         _for (imin, imax, di)
  142.            {
  143.              i = ();
  144.            .
  145.            .
  146.            }
  147.            
  148.       6.  For multiplication by 2 use the `mul2' function.  
  149.       7.  To square a number, do not use `x * x'.  Use `sqr(x)'.
  150.       
  151.  
  152. Writing Memory Efficient Routines
  153. =================================
  154.  
  155.    In the previous section, it was emphasized that routines that use the
  156.    least number of tokens are the fastest.  Since they use the smallest
  157.    number of tokens, they take up less space and and are more memory
  158.    efficient.  
  159.    
  160.    Avoid the use of literal strings wherever possible.  Strings take up more
  161.    memory than variables assigned to strings.  For example,
  162.    
  163.      define silly ()
  164.      {
  165.         if (file_exists ("my_file.txt")) 
  166.       rename ("my_file.txt", "my_file.old");
  167.     else create ("my_file.txt");
  168.      }
  169.      
  170.    should be written:
  171.    
  172.      define silly ()
  173.      {
  174.         variable file = "my_file.txt";
  175.         if (file_exists (file)) 
  176.           rename (file, "my_file.old");
  177.         else create (file);
  178.      }
  179.  
  180.    Similarly, when working with strings with 1 character, e.g., "a", if
  181.    possible, use routines that work with characters instead.  For example,
  182.    instead of using:
  183.    
  184.       insert ("a");      
  185.       if (looking_at ("a")) ...
  186.       
  187.    use:
  188.    
  189.       insert_char ('a');
  190.       if (looking_at_char ('a')) ...
  191.       
  192.    Finally, never use `""'; use `Null_String' instead.
  193.    
  194.    
  195.  
  196.