On Friday, 7 September 2018 at 16:44:05 UTC, Peter Alexander
wrote:
I recently wrote a small program of ~600 lines of code to solve
an optimisation puzzle. Profiling showed that GC allocations
were using non-trivial CPU, so I decided to try and apply @nogc
to remove allocations. This is a small experience report of my
efforts.
1. My program does some initialisation before the main solver.
I don't care about allocations in the initialisation. Since not
all of my code needed to be @nogc, I couldn't add `@nogc:` to
the top of the file and instead had to refactor my code into
initialisation parts and main loop parts and wrap the latter in
@nogc { ... }. This wasn't a major issue, but inconvenient.
2. For my code the errors were quite good. I was immediately
able to see where GC allocations were occurring and fix them.
3. It was really frustrating that I had to make the compiler
happy before I was able to run anything again. Due to point #1
I had to move code around to restructure things and wanted to
make sure everything continued working before all GC
allocations were removed.
4. I used std.algorithm.topNCopy, which is not @nogc. The error
just says "cannot call non-@nogc function [...]". I know there
are efforts to make Phobos more @nogc friendly, but seeing this
error is like hitting a brick wall. I wouldn't expect topNCopy
to use GC, but as a user, what do I do with the error? Having
to dig into Phobos source is unpleasant. Should I file a bug?
What if it is intentionally not @nogc for some subtle reason?
Do I rewrite topNCopy?
5. Sometimes I wanted to add writeln to my code to debug
things, but writeln is not @nogc, so I could not. I could have
used printf in hindsight, but was too frustrated to continue.
6. In general, peppering my code with @nogc annotations was
just unpleasant.
7. In the end I just gave up and used -vgc flag, which worked
great. I had to ignore allocations from initialisation, but
that was easy. It might be nice to have some sort of `ReportGC`
RAII struct to scope when -vgc reports the GC.
Phobos is a mine field for @nogc code. The worst thing is that
some algorithms don't just allocate, but they allocate
"sometimes". I always used "equal" without fear but one day I
instantiated "equal" with some char slices and a simple
comparison algorithm allocated. The same for fill(). Phobos is
infected here and there with allocations, if you really want to
write without GC, I wouldn't use Phobos at all.