Number: 1102

Date: 12-May-84 15':04':05

Submitter: Sannella.PA

Source: Feuerman.PASA

Subject: Document performance tradeoffs w/ usings different types of macros

Lisp Version: 

Description: '
Date': 11 May 84 13':13':34 PDT (Friday)'
From': Feuerman.PASA'
Subject': Macros'
To': LispSupport.pa'
cc': 1100Support, Feuerman'
'
I''ve been using substitution MACROs more and more on small functions, since they do work faster than even compiled code on sufficiently small functions (according to TIMEALL).  I have basically two questions':'
'
1)  Can anyone hazard a guess at how big "sufficiently small functions" are?  At what point does it become more economical to use a compiled function?'
'
2)  Has anyone written a package that will create a substitution macro form equivalent to a given definition?'
'
--Ken.'
'
-----'
'
Date': 11 May 84 15':32 PDT'
From': JonL.pa'
Subject': Re': Macros'
In-reply-to': Feuerman.PASA''s message of 11 May 84 13':13':34 PDT (Friday)'
To': Feuerman.PASA'
cc': LispSupport.pa, 1100Support.PASA'
'
Re your point 1':'
I use a "rule of thumb" about when macros are worth it in performance':'
 if its only simple code, with no surrounding lexical environment problems, then the overhead of a function call is between 5 and 10 "simple" opcodes.  A "simple" opcode is, for example, would be output by compiling any of the following kinds of operations':  LOGOR, LOGAND, LOGXOR, IPLUS, IDIFFERENCE (and maybe ITIMES) all on non-negative smallp operands; also SETQ''s and any straight-forward record fetchs or replaces are "simple" by this analogy.  Lots of other things are "simple", but I hesitate to catalogue them, partly because they are subject to change, and partly because a serious user ought to make his own timings anyway to determine questions at this level.  For example, the CONS microcode, while lengthy, generally completes in "simple" time; but this doesn''t take into account the impact caused by an overloaded  GC reference count table, nor the time to reclaim the cons cell sometime in the future.'
'
'
Re your point 2':'
In general, you can''t convert code by substituting arguments into it -- that''s why lambda-binding exists.  In the lambda calculus, most models * do not * do binding, but in fact do substition; this works out all right as long as (i) there are no side effects permissible in the language, and (ii) speed performance of substitution isn''t an issue.  On the other hand, one can very trivially convert an EXPR definition into a LAMBDA-type macro.  E.g. if'
  (DEFINEQ (FOO (X Y Z) (DECLARE (SPECVARS Y)) (LIST X Y Z Z)))'
then FOO can trivially be made into a macro by'
  (PUTPROPS FOO MACRO '
    (LAMBDA (X Y Z) (DECLARE (SPECVARS Y)) (LIST X Y Z Z)))'
and any form in your code'
  (FOO 1 2 (MUMBLE))'
will be transformed into'
  ((LAMBDA (X Y Z) (DECLARE (SPECVARS Y)) (LIST X Y Z Z)) '
    1 2 (MUMBLE))'
when compiling.  The compiler has *some* heuristics as to when a lambda application like this can be further reduced by substituting the arguments into interior form, without first binding them to the lambda variables; but I''m afraid I can''t describe any of these heuristics.  Oddly enough, in this trivial example, it manages to dispens with binding a variable Z, by simply copying the top of stack after (MUMBLE) has been computed [very clever!], but if you delete the Y in the (LIST X Y Z Z), then it falls back on the most general of schemes to compute up the arguments onto the stack, "bind" them to local variables, and then compute form by reference to these local variables.'
'
-----'
'
Date': 11 May 84 16':33':41 PDT (Friday)'
From': Feuerman.PASA'
Subject': Re': Macros'
In-reply-to': JonL.pa''s message of 11 May 84 15':32 PDT'
To': JonL.pa'
cc': Feuerman, LispSupport.pa, 1100Support'
'
Jonl,'
'
Thanks for the information.  I''m still not quite clear, however, on the difference (if any) between several of the MACROS described on page 5.18 in the manual.  The substitution macro I''ve been trying to use is the last one on the page {(LITATOM EXPRESSION)} and would be as follows':'
'
(DEFINEQ (FOO (XYZ) (DECLARE (SPECVARS Y)) (LIST X Y Z Z)))'
'
then':'
'
(PUTPROPS FOO MACRO'
  (ARGLIST (LIST ''PROGN'
                  (LIST ''DECLARE'
                     (LIST ''SPECVARS (CADR ARGLIST)))'
		  (LIST ''LIST (CAR ARGLIST) (CADR ARGLIST) '
		               (CADDR ARGLIST) (CADDR ARGLIST)]'
			       '
			       '
Do you lose any time by using your method of LAMBDA substitution, or is there any difference at all between the two methods?'
'
--Ken.  '
		    '
-----'
'
Date': 11 May 84 20':11 PDT'
From': JonL.pa'
Subject': Re': Macros'
In-reply-to': Feuerman.PASA''s message of 11 May 84 16':33':41 PDT (Friday)'
To': Feuerman.PASA'
cc': JonL.pa, LispSupport.pa, 1100Support.PASA'
'
The second type of macro described in the IRM page 5.18 is the "substitution" macro; the one in your message, the last type on page 5.18 is called a "computed" macro, because the return value for the expansion is computed by evaluating the expression.'
'
The differences in speed between a LAMBDA macro and substitution macro would depend upon whether the compiler successfully "folds out" the lambda binding.  Even if the lambda binding should occur, it probably isn''t more than 4 or 5 "simple" opcodes worth of time.'
'
Remember': for computed macros, you may wind up producing a form that doesn''t preserve the order of evaluation of the arguments, or that duplicates some expression that shouldn''t be evaluated twice.  E.g. for'
'
(FOO 1 2 (PRINT "I only want to see this message once"))'
'
The LAMBDA (and indeed, the OPENLAMBDA) would correctly evaluate the PRINT only once, binding it to a temporary local variable; a substitution macro,  ** and your particular coding of the computed macro ** would return something like '
'
(LIST 1 '
      2 '
     (PRINT "I only want to see this message once") '
     (PRINT "I only want to see this message once") )'
'
-- JonL --'
'
'


Workaround: 

Test Case: 

Edit-By: masinter.PA

Edit-Date: 13-Jul-84 18':00':38

Attn: Documentation

Assigned To: 

In/By: 

Disposition: 

System: Language Support

Subsystem: Compiler, Code Format

Machine: 

Disk: 

Microcode Version: 

Memory Size: 

File Server: 

Server Software Version: 

Difficulty: Moderate

Frequency: Everytime

Impact: Annoying

Priority: Perhaps

Status: Open

Problem Type: Documentation

Source Files: