From: Paul K. <pv...@pv...> - 2013-10-26 17:37:20
|
Douglas Katzman wrote: > Suppose you have the following > > (defun highly-popular-function (x) (mapcar #'something x)) > > where not only is this function called very often, but almost always > with X being NIL. > > On the whole it conses madly despite NIL input. Two solutions come to mind: > 1. the loop over the input should check whether there is anything to do. > if not, just return nil > 2. the "extra" cons cell that is pre-allocated for the purpose of being > able to do RPLACD down the chain can perhaps be stack-allocated [...] > Specifically, in this loop in 'mapfoo-transform' and the similar one for > 'nconc', and also for the LOOP macro (which I once found where to insert > the dx but have since forgotten), I am proposing that MAP-RESULT be > declared truly-dynamic-extent. > > (let ((temp (gensym)) > (map-result (gensym))) > `(let ((,map-result (list nil))) ; <-- this guy > (do-anonymous ((,temp ,map-result) . ,(do-clauses)) > (,endtest (truly-the list (cdr ,map-result))) > (rplacd ,temp (setq ,temp (list ,call))))))) Sounds right to me. As far as I understand, DX contagion only happens when a value is bound or rebound to a variable that is declared DX. I'm tempted to implement both suggestions and expand into something like (unless [end-tests] (tagbody [...] (when [end-tests] (return ...))) The replication ought to help rotate the loop nicely, and it also exposes more information to branch prediction. Downside: more code, but that's POLICY-able. Paul Khuong |