Bug 22155 – practical range usage often causes unnecessary closure allocations.

Status
NEW
Severity
normal
Priority
P3
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-07-28T16:06:01Z
Last change time
2024-12-01T16:39:05Z
Keywords
industry, performance
Assigned to
No Owner
Creator
John Colvin
Moved to GitHub: phobos#10470 →

Comments

Comment #0 by john.loughran.colvin — 2021-07-28T16:06:01Z
void foo(int[] a, int b) @nogc { import std.algorithm.iteration : map; size_t i = 0; foreach (el; a.map!(x => x + b)) a[i++] = el; } onlineapp.d(1): Error: function `onlineapp.foo` is `@nogc` yet allocates closures with the GC onlineapp.d(4): onlineapp.foo.__lambda4 closes over variable b at onlineapp.d(1) or the more common case for us: a.map!(x => a + b).array; which ends up allocating an unnecessary extra closure, even if `a.length` is 0. It is not clear to me exactly how this could be fixed even conceptually, but it is worth documenting as a real problem. I want to use the GC freely, but I also want to be in control. Random closures that you can't spot easily cause a lot of problems. Using `@nogc` is way too restrictive for these use cases, e.g. you might be totally fine with GC allocation *inside* the lambda, you just don't want to do another one to capture. Every allocation is individually expensive, often dwarfing the rest of the code in the function.
Comment #1 by kinke — 2021-07-29T05:12:42Z
LDC optimizes it away with -O for the 2 given testcases (via the GC2Stack IR pass) - conceptually, it can prove that the closure doesn't escape after inlining *everything*, and moves it back to the stack.
Comment #2 by robert.schadek — 2024-12-01T16:39:05Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/phobos/issues/10470 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB