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?

Semi-unrelated, but I think you should open a bug for this one. I remember Andrei stating before that every function in std.algorithm except for LevehnsteinDistance(?) is @nogc, so he either missed topNCopy or the gc-ness of the function has changed sometime between ~2015 and now.

Actually, thanks to the fact that run.dlang.io provides the ability to compile a code snippet with all compilers since 2.060, this is very easy to debug:

import std.algorithm;
import std.range;

void main()
{
    int[100] store;
    auto nums = iota(100);
    nums.topNCopy(store[]); //compiles
}

Now if I add @nogc to main:

Up to 2.060 : Failure with output: onlineapp.d(4): Error: valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @nogc

2.061 to 2.065.0: Failure with output: onlineapp.d(4): Error: undefined identifier nogc

2.066.0: Failure with output: onlineapp.d(8): Error: @nogc function 'D main' cannot call non-@nogc function 'std.algorithm.topNCopy!("a < b", Result, int[]).topNCopy'

2.067.1 to 2.078.1: Failure with output: onlineapp.d(8): Error: @nogc function 'D main' cannot call non-@nogc function 'std.algorithm.sorting.topNCopy!("a < b", Result, int[]).topNCopy'

Since 2.079.1: Failure with output: onlineapp.d(8): Error: `@nogc` function `D main` cannot call non-@nogc function `std.algorithm.sorting.topNCopy!("a < b", Result, int[]).topNCopy`

So it seems that it's never worked. Looking at the implementation, it uses a std.container.BinaryHeap, so it'd require a small rewrite to work with @nogc.

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.

You are allowed to call "@gc" functions inside @nogc functions if you prefix them with a debug statement, e.g.:

void main() @nogc
{
    debug topNCopy(source, target);
}

You then have to pass the appropriate switch to the compiler to tell it to compile in the debug code.

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.

I've been thinking lately that @nogc may have been going to far, and -vgc was all that was actually needed. -vgc gives you the freedom to remove or ignore GC allocations as necessary, instead of @nogc's all or nothing approach.

Reply via email to