On Thursday, 9 October 2014 at 15:32:06 UTC, Andrei Alexandrescu
wrote:
On 10/9/14, 7:09 AM, Dicebot wrote:
Yes and this is exactly why I am that concerned about recent
memory
management policy thread. Don has already stated it in his
talks but I
will repeat important points:
1) We don't try to avoid GC in any way
2) However it is critical for performance to avoid creating
garbage in a
form of new GC roots
3) Worst part of Phobos is not GC allocations but specifically
lot of
temporarily garbage allocations
What would be a few good examples of (3)? Thanks.
Infamous setExtensions
(https://github.com/D-Programming-Language/phobos/blob/master/std/path.d#L843)
immediately comes to mind. Usage of concatenation operators there
allocates a new GC root for a new string.
This is a very simple issue that will prevent us from using and
contributing to majority of Phobos even when D2 port is
finished.
Switch to input/output ranges as API fundamentals was supposed
to fix
it.
Unfortunately it doesn't. RC does. Lazy computation relies on
escaping ranges all over the place (i.e. as fields inside
structs implementing the lazy computation). If there's no way
to track those many tidbits, resources cannot be reclaimed
timely.
Are you trying to tell me programs I work with do not exist? :)
Usage of output range is simply a generalization of out array
parameter used in both Tango and our code. It is _already_ proved
to work for our cases. Usage of input ranges is less important
but it fits existing Phobos style better.
We also don't usually reclaim resources. Out application usually
work by growing constant amount of buffers to the point where
they can handle routine workload and staying there will almost 0
GC activity.
I don't understand statement about storing the ranges. The way I
have it in mind ranges are tool for algorithm composition. Once
you want to store it as a struct field you force range evaluation
via output range and store resulting allocated buffer. In user
code.
Custom management policies as you propose won't fix it at all
because garbage will still be there, simply managed in a
different way.
I'm not sure I understand this.
Typical pattern from existing D1 code:
// bad
auto foo(char[] arg)
{
return arg ~ "aaa";
}
vs
// good
auto foo(char[] arg, ref char[] result)
{
result.length = arg.length +3; // won't allocate if already
has capacity
result[0 .. arg.length] = arg[];
result[arg.length .. arg.length + 3] = "aaa"[];
}
It doesn't matter if first snippet allocates GC root or
ref-counted root. We need the version that does not allocate new
root at all (second snippet).