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:
---BEGIN asciitable.d---
import std.string;
import std.stdio;
string fmttable(ref string[][] table) {
string res = "";
// column widths
int[] widths;
if (table.length == 0) return "";
widths.length = table[0].length;
for (int colnum=0; colnum < table[0].length; colnum++) {
int width = 0;
for (int rownum=0; rownum < table.length; rownum++) {
if (table[rownum][colnum].length > width)
width = cast(int) table[rownum][colnum].length;
}
widths[colnum] = width;
}
for (int rownum=0; rownum < table.length; rownum++) {
res ~= "|";
for (int colnum=0; colnum < table[rownum].length;
colnum++) {
res ~= leftJustify(table[rownum][colnum],
widths[colnum]);
res ~= "|";
}
res ~= "\n";
}
return res;
}
void main() {
// tiny table (1x1)
/*
string[][] table = [
["row1.1"],
];
*/
// small table (3x5)
string[][] 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);
}
}
---END asciitable.d---
Perl version:
---BEGIN asciitable.pl---
#!/usr/bin/env perl
sub fmttable {
my $table = shift;
my $res = "";
# column widths
my @widths;
if (@$table == 0) { return "" }
for my $colnum (0 .. $#{$table->[0]}) {
my $width = 0;
for my $rownum (0 .. $#{$table}) {
if (length($table->[$rownum][$colnum]) > $width) {
$width = length($table->[$rownum][$colnum]);
}
}
$widths[$colnum] = $width;
}
for my $rownum (0..$#{$table}) {
$res .= "|";
for my $colnum (0..$#{$table->[$rownum]}) {
$res .= sprintf("%-".$widths[$colnum]."s|",
$table->[$rownum][$colnum]);
}
$res .= "\n";
}
$res;
}
# tiny table (1x1)
#my $table = [["row1.1"]];
# small table (3x5)
my $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"],
];
print fmttable($table);
for (1..1_000_000) {
fmttable($table);
}
---END asciitable.pl---
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?