On Friday, 19 March 2021 at 17:10:27 UTC, Ali Çehreli wrote:
Jon mentioned how PR 7678 reduced the performance of
std.regex.matchOnce. After analyzing the code we realized that
the performance loss must be due to two delegate context
allocations:
https://github.com/dlang/phobos/pull/7678/files#diff-269abc020de3a951eaaa5b8eca5a0700ba8b298767c7a64f459e74e1531a80aeR825
One delegate is 'matchOnceImp' and the other one is the
anonymous delegate created on the return expression.
We understood that 'matchOnceImp' could not be a nested
function because of an otherwise useful rule: the name of the
nested function alone would *call* that function instead of
being a symbol for it. That is not the case for a local
delegate variable, so that's why 'matchOnceImp' exists as a
delegate variable there.
Then there is the addition of the 'pure' attribute to it.
Fine...
After tinkering with the code, we realized that the same effect
can be achieved with a static member function of a static
struct, which would not allocate any delegate context. I add
@nogc to the following code to prove that point. The following
code is even simpler than Jon and I came up with yesterday.
[... Code snippet removed ...]
There: we injected @trusted code inside a @nogc @safe function.
Question to others: Did we understand the reason for the
convoluted code in that PR fully? Is the above method really a
better solution?
I submitted PR 7902 (https://github.com/dlang/phobos/pull/7902)
to address this. I wasn't able to use the version Ali showed in
the post, but the PR does use what is essentially the same idea
identified at the D Meetup. It is a performance regression, and
is a bit more nuanced than would be ideal. Comments and review
would be appreciated.
--Jon