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?

Reply via email to