Subject: Re: bug#17147: Performance regression by 3000000% for evaluating "and" form

From: Mark H Weaver <[email-masked]>
Date: Mon, 31 Mar 2014 18:30:45 -0400

severity 17147 wishlist
thanks

David Kastrup <[email-masked]> writes:

> The following program goes from 2.3ms execution time to 80s execution
> time when going from Guile-1.8 to current master.
>
> (use-modules (srfi srfi-19))
> (define start-time (current-time))
> (primitive-eval (cons 'and (make-list 10000 #f)))
> (display (time-difference (current-time) start-time))

I suspect the reason this works well on Guile 1.8 is that macros are
expanded lazily, and since the first argument is #f, it doesn't need to
expand the rest.

Guile 2.0 uses a different macro expander which is vastly superior in
most respects and needed to support modern Scheme programs, but it is
not lazy.  Guile 2 is primarily designed to work in a compiled mode
anyway, where laziness is pointless and would most likely slow things
down.

(and x y ...) expands into (if x (and y ...) #f), so your huge 'and'
form turns into a very deeply nested expression, and this overflows the
compiler's stack on Guile 2.0.x.  Thanks to Andy's recent work on
expandable stacks in master, this case works properly there.

While it would of course be ideal for our compiler to efficiently handle
expressions 10000 levels deep (if it can be done without sacrificing
maintainability), dealing with such pathological cases should not be a
high priority, IMO.  There are many more important things to work on.

Is this just an academic exercise, or does Lilypond generate massively
huge expressions like this?

      Mark