Thread overview
[Issue 19705] Static foreach slow for numeric ranges
Feb 27, 2019
Stefan Koch
Jun 22, 2020
Boris Carvajal
Jun 25, 2020
Dlang Bot
Jun 28, 2020
Dlang Bot
February 27, 2019
https://issues.dlang.org/show_bug.cgi?id=19705

Stefan Koch <uplink.coder@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |uplink.coder@gmail.com

--- Comment #1 from Stefan Koch <uplink.coder@gmail.com> ---
I can shed light on the reason, at least.
So static foreach is conceptually just syntactic sugar over tuple foreach.
As such it works in two steps

1. Create a type-tuple from the numeric range.
2. Iterate the type-tuple.

To iterate a tuple we need to expand tuples which may be elements of the tuple
such that: tuple(1,2,3,tuple(4,5,6)) becomes tuple(1,2,3,4,5,6);
that process has to be done lazily since a tuple could be generated on the fly
to model infinite sequences.

therefore iteration over three elements would go like this
(ResultElems[] elems;
elem[0] = iterateTuple(t); resetTuple(t);
iterateTuple(t); elems[1] = iterateTuple(t); resetTuple(t);
iterateTuple(t); iterateTuple(t); elems[2] = iterateTuple(t); resetTuple(t);
)
as you can this O(n!) (factorial)
and that's why it's slow.

Templates suffer from the same problem, and the compiler does some work to memorize previous instances which effectively diminishes the factorial term (it's technically still there though and can dominate if N gets large enough!)

One way to slove this is to keep tuple_expansion state when iterating/expanding the tuple which would effectively diminish the factorial term rather well.

--
June 22, 2020
https://issues.dlang.org/show_bug.cgi?id=19705

Boris Carvajal <boris2.9@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |boris2.9@gmail.com

--- Comment #2 from Boris Carvajal <boris2.9@gmail.com> ---
I made a change that improve these cases. https://github.com/dlang/dmd/pull/11303

Now:

    static foreach (i; 0..10000) {}

is faster than:

    alias A = generate!10000;
    static foreach (i; A) {}

as it should be.

--
June 25, 2020
https://issues.dlang.org/show_bug.cgi?id=19705

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #3 from Dlang Bot <dlang-bot@dlang.rocks> ---
@BorisCarvajal updated dlang/dmd pull request #11303 "static foreach over array and numeric range speed up by ~7x" fixing this issue:

- Fix Issue 19705 - Static foreach slow for numeric ranges

https://github.com/dlang/dmd/pull/11303

--
June 28, 2020
https://issues.dlang.org/show_bug.cgi?id=19705

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #4 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11303 "static foreach over array and numeric range speed up by ~7x" was merged into master:

- ef66363709b9de8bef5f48ba56dc1c1a1c545770 by Boris Carvajal:
  Fix Issue 19705 - Static foreach slow for numeric ranges

https://github.com/dlang/dmd/pull/11303

--