Thread overview | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 12, 2015 DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
code: import std.stdio; auto fmttable(immutable(string[][]) table) { import std.array : appender, uninitializedArray; import std.range : take, repeat; import std.exception : assumeUnique; auto res = appender(uninitializedArray!(char[])(128)); res.clear(); if (table.length == 0) return ""; // column widths auto widths = new int[](table[0].length); foreach (rownum, row; table) { foreach (colnum, cell; row) { if (cell.length > widths[colnum]) widths[colnum] = cast(int)cell.length; } } foreach (row; table) { res ~= "|"; foreach (colnum, cell; row) { int l = widths[colnum] - cast(int)cell.length; res ~= cell; if (l) res ~= ' '.repeat().take(l); res ~= "|"; } res.put("\n"); } return res.data.assumeUnique(); } void main() { immutable table = [ ["row1.1", "row1.2 ", "row1.3"], ["row2.1", "row2.2", "row2.3"], ["row3.1", "row3.2", "row3.3 "], ["row4.1", "row4.2", "row4.3"], ["row5.1", "row5.2", "row5.3"], ]; writeln(fmttable(table)); int i; for (i=0; i < 1000000; ++i) { fmttable(table); } writeln(i); } timings: DMD (-O -release -inline -boundscheck=off): real 0m0.003s user 0m0.000s sys 0m0.000s LDMD2-ldc2 (-O -release -inline -boundscheck=off): real 0m1.071s user 0m1.067s sys 0m0.000s GDC (-O3 -finline -frelease -fno-bounds-check): real 0m0.724s user 0m0.720s sys 0m0.003s |
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak | On Thursday, 12 November 2015 at 11:59:50 UTC, Daniel Kozak wrote:
> code:
>
> import std.stdio;
>
> auto fmttable(immutable(string[][]) table) {
>
> import std.array : appender, uninitializedArray;
> import std.range : take, repeat;
> import std.exception : assumeUnique;
>
> auto res = appender(uninitializedArray!(char[])(128));
> res.clear();
>
> if (table.length == 0) return "";
> // column widths
> auto widths = new int[](table[0].length);
>
> foreach (rownum, row; table) {
> foreach (colnum, cell; row) {
> if (cell.length > widths[colnum])
> widths[colnum] = cast(int)cell.length;
> }
> }
>
> foreach (row; table) {
> res ~= "|";
> foreach (colnum, cell; row) {
> int l = widths[colnum] - cast(int)cell.length;
> res ~= cell;
> if (l)
> res ~= ' '.repeat().take(l);
> res ~= "|";
> }
> res.put("\n");
> }
>
> return res.data.assumeUnique();
> }
>
> void main() {
>
> immutable table = [
> ["row1.1", "row1.2 ", "row1.3"],
> ["row2.1", "row2.2", "row2.3"],
> ["row3.1", "row3.2", "row3.3 "],
> ["row4.1", "row4.2", "row4.3"],
> ["row5.1", "row5.2", "row5.3"],
> ];
>
> writeln(fmttable(table));
> int i;
> for (i=0; i < 1000000; ++i) {
> fmttable(table);
> }
> writeln(i);
> }
>
> timings:
>
> DMD (-O -release -inline -boundscheck=off):
> real 0m0.003s
> user 0m0.000s
> sys 0m0.000s
>
> LDMD2-ldc2 (-O -release -inline -boundscheck=off):
> real 0m1.071s
> user 0m1.067s
> sys 0m0.000s
>
>
> GDC (-O3 -finline -frelease -fno-bounds-check):
> real 0m0.724s
> user 0m0.720s
> sys 0m0.003s
What versions of these compilers? I suspect the majority (maybe 80%-ish) of the time is spent allocating memory, so you might be seeing GC improvements in recent DMD
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | V Thu, 12 Nov 2015 12:10:30 +0000
John Colvin via Digitalmars-d <digitalmars-d@puremagic.com> napsáno:
> On Thursday, 12 November 2015 at 11:59:50 UTC, Daniel Kozak wrote:
> > code:
> >
> > import std.stdio;
> >
> > auto fmttable(immutable(string[][]) table) {
> >
> > import std.array : appender, uninitializedArray;
> > import std.range : take, repeat;
> > import std.exception : assumeUnique;
> >
> > auto res = appender(uninitializedArray!(char[])(128));
> > res.clear();
> >
> > if (table.length == 0) return "";
> > // column widths
> > auto widths = new int[](table[0].length);
> >
> > foreach (rownum, row; table) {
> > foreach (colnum, cell; row) {
> > if (cell.length > widths[colnum])
> > widths[colnum] = cast(int)cell.length;
> > }
> > }
> >
> > foreach (row; table) {
> > res ~= "|";
> > foreach (colnum, cell; row) {
> > int l = widths[colnum] - cast(int)cell.length;
> > res ~= cell;
> > if (l)
> > res ~= ' '.repeat().take(l);
> > res ~= "|";
> > }
> > res.put("\n");
> > }
> >
> > return res.data.assumeUnique();
> > }
> >
> > void main() {
> >
> > immutable table = [
> > ["row1.1", "row1.2 ", "row1.3"],
> > ["row2.1", "row2.2", "row2.3"],
> > ["row3.1", "row3.2", "row3.3 "],
> > ["row4.1", "row4.2", "row4.3"],
> > ["row5.1", "row5.2", "row5.3"],
> > ];
> >
> > writeln(fmttable(table));
> > int i;
> > for (i=0; i < 1000000; ++i) {
> > fmttable(table);
> > }
> > writeln(i);
> > }
> >
> > timings:
> >
> > DMD (-O -release -inline -boundscheck=off):
> > real 0m0.003s
> > user 0m0.000s
> > sys 0m0.000s
> >
> > LDMD2-ldc2 (-O -release -inline -boundscheck=off):
> > real 0m1.071s
> > user 0m1.067s
> > sys 0m0.000s
> >
> >
> > GDC (-O3 -finline -frelease -fno-bounds-check):
> > real 0m0.724s
> > user 0m0.720s
> > sys 0m0.003s
>
> What versions of these compilers? I suspect the majority (maybe 80%-ish) of the time is spent allocating memory, so you might be seeing GC improvements in recent DMD
DMD 2.069
LDC 2.067
GDC 2.065
No it is not cause by memory allocations.
It seems DMD can recognize that fmttable has same result every time, so it does compute it only once.
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak Attachments:
| On 12 November 2015 at 12:59, Daniel Kozak via Digitalmars-d < digitalmars-d@puremagic.com> wrote: > code: > > <snip> > > GDC (-O3 -finline -frelease -fno-bounds-check): > real 0m0.724s > user 0m0.720s > sys 0m0.003s > > Not to be pedantic, but -finline does nothing (what you really want is -finline-functions) However.... -finline-functions is enabled automatically at -O3, so the whole -finline just becomes wasted typing. :-) |
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak | On Thursday, 12 November 2015 at 12:23:11 UTC, Daniel Kozak wrote:
> V Thu, 12 Nov 2015 12:10:30 +0000
> John Colvin via Digitalmars-d <digitalmars-d@puremagic.com> napsáno:
>
>> On Thursday, 12 November 2015 at 11:59:50 UTC, Daniel Kozak wrote:
>> > [...]
>>
>> What versions of these compilers? I suspect the majority (maybe 80%-ish) of the time is spent allocating memory, so you might be seeing GC improvements in recent DMD
>
> DMD 2.069
>
> LDC 2.067
>
> GDC 2.065
>
> No it is not cause by memory allocations.
>
> It seems DMD can recognize that fmttable has same result every time, so it does compute it only once.
Ok, then my second hypothesis is that dmd is inferring the pure attribute for fmttable because it returns auto (new in 2.069 IIRC), which enable the above optimisation that you have noted. Gdc and ldc (and dmd) can do similar things in their backend, but perhaps not here.
Do you have older dmd versions on hand to test?
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
V Thu, 12 Nov 2015 13:37:28 +0100
Iain Buclaw via Digitalmars-d <digitalmars-d@puremagic.com> napsáno:
> On 12 November 2015 at 12:59, Daniel Kozak via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
> > code:
> >
> >
> <snip>
>
>
> >
> > GDC (-O3 -finline -frelease -fno-bounds-check):
> > real 0m0.724s
> > user 0m0.720s
> > sys 0m0.003s
> >
> >
> Not to be pedantic, but -finline does nothing (what you really want is
> -finline-functions)
>
> However.... -finline-functions is enabled automatically at -O3, so the whole -finline just becomes wasted typing. :-)
Yeah I know, but it is a bad habit from past
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | V Thu, 12 Nov 2015 12:38:47 +0000
John Colvin via Digitalmars-d <digitalmars-d@puremagic.com> napsáno:
> On Thursday, 12 November 2015 at 12:23:11 UTC, Daniel Kozak wrote:
> > V Thu, 12 Nov 2015 12:10:30 +0000
> > John Colvin via Digitalmars-d <digitalmars-d@puremagic.com>
> > napsáno:
> >
> >> On Thursday, 12 November 2015 at 11:59:50 UTC, Daniel Kozak wrote:
> >> > [...]
> >>
> >> What versions of these compilers? I suspect the majority (maybe 80%-ish) of the time is spent allocating memory, so you might be seeing GC improvements in recent DMD
> >
> > DMD 2.069
> >
> > LDC 2.067
> >
> > GDC 2.065
> >
> > No it is not cause by memory allocations.
> >
> > It seems DMD can recognize that fmttable has same result every time, so it does compute it only once.
>
> Ok, then my second hypothesis is that dmd is inferring the pure attribute for fmttable because it returns auto (new in 2.069 IIRC), which enable the above optimisation that you have noted. Gdc and ldc (and dmd) can do similar things in their backend, but perhaps not here.
>
> Do you have older dmd versions on hand to test?
Yes (DVM) and it is same for older versions (2.066.1, 2.067.1)
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Kozak | On Thursday, 12 November 2015 at 11:59:50 UTC, Daniel Kozak wrote:
> code:
>
> import std.stdio;
>
> auto fmttable(immutable(string[][]) table) {
>
> import std.array : appender, uninitializedArray;
> import std.range : take, repeat;
> import std.exception : assumeUnique;
>
> auto res = appender(uninitializedArray!(char[])(128));
> res.clear();
>
> if (table.length == 0) return "";
> // column widths
> auto widths = new int[](table[0].length);
>
> foreach (rownum, row; table) {
> foreach (colnum, cell; row) {
> if (cell.length > widths[colnum])
> widths[colnum] = cast(int)cell.length;
> }
> }
>
> foreach (row; table) {
> res ~= "|";
> foreach (colnum, cell; row) {
> int l = widths[colnum] - cast(int)cell.length;
> res ~= cell;
> if (l)
> res ~= ' '.repeat().take(l);
> res ~= "|";
> }
> res.put("\n");
> }
>
> return res.data.assumeUnique();
> }
>
> void main() {
>
> immutable table = [
> ["row1.1", "row1.2 ", "row1.3"],
> ["row2.1", "row2.2", "row2.3"],
> ["row3.1", "row3.2", "row3.3 "],
> ["row4.1", "row4.2", "row4.3"],
> ["row5.1", "row5.2", "row5.3"],
> ];
>
> writeln(fmttable(table));
> int i;
> for (i=0; i < 1000000; ++i) {
> fmttable(table);
> }
> writeln(i);
> }
>
> timings:
>
> DMD (-O -release -inline -boundscheck=off):
> real 0m0.003s
> user 0m0.000s
> sys 0m0.000s
>
> LDMD2-ldc2 (-O -release -inline -boundscheck=off):
> real 0m1.071s
> user 0m1.067s
> sys 0m0.000s
>
>
> GDC (-O3 -finline -frelease -fno-bounds-check):
> real 0m0.724s
> user 0m0.720s
> sys 0m0.003s
To test the speed of fmttable itself I split fmttable and main in to different modules, made fmttable extern(C) so I could just prototype it in the main module (no import), then compiled them separately before linking. This should prevent any possible inlining/purity cleverness. ~1s for ldmd2, ~2s for dmd, which is business as normal.
dmd is being clever and spotting that fmttable is pure, it would be good if ldc/gdc could spot this to.
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Colvin | On Thursday, 12 November 2015 at 14:44:49 UTC, John Colvin wrote:
>
> dmd is being clever and spotting that fmttable is pure, it would be good if ldc/gdc could spot this to.
I don't recall seeing anything in the 2.069.0 change log about improved attribute inference for auto functions. If you can find a link pointing to where it was discussed (either change log or forum or bug report), I would appreciate it.
|
November 12, 2015 Re: DMD is faster than LDC and GDC | ||||
---|---|---|---|---|
| ||||
On 11/12/15 13:22, Daniel Kozak via Digitalmars-d wrote: >>> timings: >>> > > >>> > > DMD (-O -release -inline -boundscheck=off): >>> > > real 0m0.003s >>> > > user 0m0.000s >>> > > sys 0m0.000s >>> > > >>> > > LDMD2-ldc2 (-O -release -inline -boundscheck=off): >>> > > real 0m1.071s >>> > > user 0m1.067s >>> > > sys 0m0.000s >>> > > >>> > > >>> > > GDC (-O3 -finline -frelease -fno-bounds-check): >>> > > real 0m0.724s >>> > > user 0m0.720s >>> > > sys 0m0.003s >> > >> > What versions of these compilers? I suspect the majority (maybe 80%-ish) of the time is spent allocating memory, so you might be seeing GC improvements in recent DMD > DMD 2.069 > > LDC 2.067 > > GDC 2.065 > > No it is not cause by memory allocations. > > It seems DMD can recognize that fmttable has same result every time, so it does compute it only once. Comparisons using different frontend versions are very unfair - - *every D release introduces a new language dialect* (for example: http://dlang.org/changelog/2.068.0.html#attribinference3). Out of curiosity, how does this slightly more sane version perform? (I don't have any dmd or ldc compilers; it takes ~80ms using GDC) import std.stdio; auto fmttable(alias sink=sink)(immutable(string[][]) table) { import std.range : take, repeat; if (table.length == 0) return; // column widths auto widths = new int[](table[0].length); foreach (rownum, row; table) { foreach (colnum, cell; row) { if (cell.length > widths[colnum]) widths[colnum] = cast(int)cell.length; } } foreach (row; table) { sink("|"); foreach (colnum, cell; row) { sink(cell, ' '.repeat().take(widths[colnum]-cast(int)cell.length), "|"); } sink("\n"); } } void sink(S...)(S s) { foreach(I, _; S) write(s[I]); } void sink0(S...)(S s) {} void main() { immutable table = [ ["row1.1", "row1.2 ", "row1.3"], ["row2.1", "row2.2", "row2.3"], ["row3.1", "row3.2", "row3.3 "], ["row4.1", "row4.2", "row4.3"], ["row5.1", "row5.2", "row5.3"], ]; fmttable(table); int i; for (i=0; i < 1000000; ++i) { fmttable!sink0(table); } sink(i, "\n"); } artur |
Copyright © 1999-2021 by the D Language Foundation