V Thu, 12 Nov 2015 09:12:32 +0000 Daniel Kozak via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> napsáno:
> On Wednesday, 11 November 2015 at 13:32:00 UTC, perlancar wrote: > > Here's my first non-hello-world D program, which is a direct > > translation from the Perl version. I was trying to get a feel > > about D's performance: > > > > ... > > > > While I am quite impressed with how easy I was able to write D, > > I am not so impressed with the performance. Using rdmd (build > > 20151103), the D program runs in 17.127s while the Perl version > > runs in 11.391s (so the D version is quite a bit *slower* than > > Perl's). While using gdc (Debian 4.9.2-10), I am able to run it > > in 3.988s (only about 3x faster than Perl's version). > > > > I understand that string processing (concatenation, allocation) > > is quite optimized in Perl, I was wondering if the D version > > could still be sped up significantly? > > Main problem is with allocations and with stripLeft, here is my > version which is 10x faster than perls even with DMD. With LDC is > 12x faster > > import std.stdio; > import std.array : appender; > import std.range; > > > auto fmttable(T)(T table) { > auto res = appender!(string)(); > res.reserve(64); > > 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.put("|"); > foreach (colnum, cell; row) { > int l = widths[colnum] - cast(int)cell.length; > res.put(cell); > if (l) > res.put(' > '.repeat().take(l)); res.put("|"); > } > res.put("\n"); > } > > return res.data; > } > > void main() { > > auto 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"], > ]; > > write(fmttable(table)); > for (int i=0; i < 1000000; ++i) { > fmttable(table); > } > } > > or with ~ operator: import std.stdio; auto fmttable(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() { auto 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"], ]; write(fmttable(table)); for (int i=0; i < 1000000; ++i) { fmttable(table); } }