Re: Looking for some thoughtful review of my first D program

2023-12-30 Thread Renato via Digitalmars-d-learn
On Wednesday, 27 December 2023 at 11:08:26 UTC, Thomas Teixeira 
wrote:

Hi, you all !

I've wanted to look at D for the last two years, being a C 
fanboy and not fond of C++.
It seemed like a good alternative between some delightful extra 
new stuff and keeping C-like experience : performances and code 
style wise.


I wrote my first CLI program this weekend and would like some 
code review, if some of you don't mind. :)
The source code can be found here : 
https://git.sr.ht/~nasmevka/tmp/tree/main/item/tmp.d


I apologize for the way my code looks like. I do not use LSPs 
and having function definition's name on their own line make 
`grep ^funcname` really powerful.


Templates are really powerful, and I feel like I do not use 
them near enough ? 路



Open to all form of criticism ☺️


Your code seems pretty good to me :)

Just one minor comment:

```d
File file = File(filename, "w");
scope(exit) file.close;
```

You don't need to close the file because that's done 
automatically as the `file` goes out of scope (as explained [in 
the docs](https://dlang.org/library/std/stdio/file.html)).


I believe it uses 
[RefCounted](https://dlang.org/library/std/typecons/safe_ref_counted.html) to do that.


Looking for some thoughtful review of my first D program

2023-12-27 Thread Thomas Teixeira via Digitalmars-d-learn

Hi, you all !

I've wanted to look at D for the last two years, being a C fanboy 
and not fond of C++.
It seemed like a good alternative between some delightful extra 
new stuff and keeping C-like experience : performances and code 
style wise.


I wrote my first CLI program this weekend and would like some 
code review, if some of you don't mind. :)
The source code can be found here : 
https://git.sr.ht/~nasmevka/tmp/tree/main/item/tmp.d


I apologize for the way my code looks like. I do not use LSPs and 
having function definition's name on their own line make `grep 
^funcname` really powerful.


Templates are really powerful, and I feel like I do not use them 
near enough ? 路



Open to all form of criticism ☺️


Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn

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 < 100; ++i) {
fmttable(table);
}
}




Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn
V Thu, 12 Nov 2015 09:12:32 +
Daniel Kozak via Digitalmars-d-learn
 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 < 100; ++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 < 100; ++i) {
fmttable(table);
}
}



Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn
V Thu, 12 Nov 2015 11:03:38 +
Tobias Pankrath via Digitalmars-d-learn
 napsáno:

> > or with ~ operator:
> >
> > import std.stdio;
> >
> > [...]  
> 
> Did anyone check that the last loop isn't optimized out?

Yes, it is not optimized out

> Could also be improved further if you make the function take an
> output range and reuse one appender for every call, but that might be
> to far off the original perl solution.

I agree, that would be to far off the original solution.



Re: my first D program (and benchmark against perl)

2015-11-12 Thread perlancar via Digitalmars-d-learn
On Wednesday, 11 November 2015 at 14:20:51 UTC, Rikki Cattermole 
wrote:
I turned it into mostly using large allocations, instead of 
small ones.
Although I'd recommend using Appender instead of my custom 
functions for this.


Oh and for me, I got it at 2 secs, 513 ms, 397 μs, and 5 
hnsecs. Unoptimized, using dmd.
When release mode is enabled on dmd: 1 sec, 550 ms, 838 μs, and 
9 hnsecs. So significant improvement even with dmds awful 
optimizer.


Hi Rikki,

Thanks. With your version, I've managed to be ~4x faster:

dmd  : 0m1.588s
dmd (release): 0m1.010s
gdc  : 0m2.093s
ldc  : 0m1.594s

Perl version : 0m11.391s

So, I'm satisfied enough with the speed for now. Turns out dmd is 
not always slower.


Re: my first D program (and benchmark against perl)

2015-11-12 Thread perlancar via Digitalmars-d-learn
On Wednesday, 11 November 2015 at 14:26:32 UTC, Andrea Fontana 
wrote:

Did you try rdmd -O -noboundscheck -release yourscript.d ?


I just did. It improves speed from 17.127s to 14.831s. Nice, but 
nowhere near gdc/ldc level.


You should try using appender!string rather than concatenate 
(http://dlang.org/phobos/std_array.html#.Appender) using 
capacity 
(http://dlang.org/phobos/std_array.html#.Appender.capacity) to 
improve performace.



You should also switch from for to foreach.


Thanks for the above 2 tips.



Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn
V Thu, 12 Nov 2015 12:13:10 +
perlancar via Digitalmars-d-learn 
napsáno:

> On Wednesday, 11 November 2015 at 14:20:51 UTC, Rikki Cattermole 
> wrote:
> > I turned it into mostly using large allocations, instead of 
> > small ones.
> > Although I'd recommend using Appender instead of my custom 
> > functions for this.
> >
> > Oh and for me, I got it at 2 secs, 513 ms, 397 μs, and 5 
> > hnsecs. Unoptimized, using dmd.
> > When release mode is enabled on dmd: 1 sec, 550 ms, 838 μs, and 
> > 9 hnsecs. So significant improvement even with dmds awful 
> > optimizer.  
> 
> Hi Rikki,
> 
> Thanks. With your version, I've managed to be ~4x faster:
> 
> dmd  : 0m1.588s
> dmd (release): 0m1.010s
> gdc  : 0m2.093s
> ldc  : 0m1.594s
> 
> Perl version : 0m11.391s
> 
> So, I'm satisfied enough with the speed for now. Turns out dmd is 
> not always slower.

It depends which flags do you use on ldc and gdc


ldc (-singleobj -release -O3 -boundscheck=off)
gdc (-O3 -finline -frelease -fno-bounds-check)



Re: my first D program (and benchmark against perl)

2015-11-12 Thread Tobias Pankrath via Digitalmars-d-learn

or with ~ operator:

import std.stdio;

[...]


Did anyone check that the last loop isn't optimized out? Could 
also be improved further if you make the function take an output 
range and reuse one appender for every call, but that might be to 
far off the original perl solution.


Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn

On Thursday, 12 November 2015 at 12:25:08 UTC, Daniel Kozak wrote:

V Thu, 12 Nov 2015 12:13:10 +
perlancar via Digitalmars-d-learn 


napsáno:

On Wednesday, 11 November 2015 at 14:20:51 UTC, Rikki 
Cattermole wrote:

> I turned it into mostly using large allocations, instead of
> small ones.
> Although I'd recommend using Appender instead of my custom
> functions for this.
>
> Oh and for me, I got it at 2 secs, 513 ms, 397 μs, and 5
> hnsecs. Unoptimized, using dmd.
> When release mode is enabled on dmd: 1 sec, 550 ms, 838 μs, 
> and

> 9 hnsecs. So significant improvement even with dmds awful
> optimizer.

Hi Rikki,

Thanks. With your version, I've managed to be ~4x faster:

dmd  : 0m1.588s
dmd (release): 0m1.010s
gdc  : 0m2.093s
ldc  : 0m1.594s

Perl version : 0m11.391s

So, I'm satisfied enough with the speed for now. Turns out dmd 
is not always slower.


It depends which flags do you use on ldc and gdc


ldc (-singleobj -release -O3 -boundscheck=off)
gdc (-O3 -finline -frelease -fno-bounds-check)


import std.stdio;

auto fmttable(string[][] table) {

import std.array : appender, uninitializedArray;
import std.range : take, repeat;
import std.exception : assumeUnique;


if (table.length == 0) return "";
// column widths
auto widths = new int[](table[0].length);
	size_t total = (table[0].length + 1) * table.length + 
table.length;	


foreach (rownum, row; table) {
foreach (colnum, cell; row) {
if (cell.length > widths[colnum])
widths[colnum] = cast(int)cell.length;
}
}

foreach (colWidth; widths)
{
total += colWidth * table.length;
}   

auto res = appender(uninitializedArray!(char[])(total));
res.clear();

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"],
];

writeln(fmttable(table));
for (int i=0; i < 100; ++i) {
fmttable(table);
}
}

dmd -O -release -inline -boundscheck=off  asciitable.d

real0m1.463s
user0m1.453s
sys 0m0.003s


ldc2 -singleobj -release -O3 -boundscheck=off asciitable.d

real0m0.945s
user0m0.940s
sys 0m0.000s

gdc -O3 -finline -frelease -fno-bounds-check -o asciitable 
asciitable.d


real0m0.618s
user0m0.613s
sys 0m0.000s


perl:

real0m14.198s
user0m14.170s
sys 0m0.000s


Re: my first D program (and benchmark against perl)

2015-11-12 Thread Daniel Kozak via Digitalmars-d-learn

On Thursday, 12 November 2015 at 12:49:55 UTC, Daniel Kozak wrote:
On Thursday, 12 November 2015 at 12:25:08 UTC, Daniel Kozak 
wrote:

... 
auto res = appender(uninitializedArray!(char[])(total));
res.clear();
...


this is faster for DMD and ldc:

auto res = appender!(string)();
res.reserve(total);

but for gdc(fronend version 2.066) it makes it two times slower 
(same for dmd, ldc 2.066 and older)





Re: my first D program (and benchmark against perl)

2015-11-12 Thread perlancar via Digitalmars-d-learn

On Thursday, 12 November 2015 at 12:49:55 UTC, Daniel Kozak wrote:

dmd -O -release -inline -boundscheck=off  asciitable.d

real0m1.463s
user0m1.453s
sys 0m0.003s


ldc2 -singleobj -release -O3 -boundscheck=off asciitable.d

real0m0.945s
user0m0.940s
sys 0m0.000s

gdc -O3 -finline -frelease -fno-bounds-check -o asciitable 
asciitable.d


real0m0.618s
user0m0.613s
sys 0m0.000s


perl:

real0m14.198s
user0m14.170s
sys 0m0.000s


Nice! Seems like I can get a further 100% improvement in speed 
from the last version (so a total of ~8x speedup from my original 
D version). Now I wonder how C would fare...




Re: my first D program (and benchmark against perl)

2015-11-11 Thread Edwin van Leeuwen via Digitalmars-d-learn

On Wednesday, 11 November 2015 at 13:32:00 UTC, perlancar wrote:

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";


Not sure if this will be faster, but you could try rewriting the 
above for loop

with more functional code (code below is untested):

table.map!((col)
  { return zip(col,widths)
  .map!( (e) => leftJustify(e[0], e[1] ) )
  .join("|");
  }).join("\n");

Cheers,

Edwin


Re: my first D program (and benchmark against perl)

2015-11-11 Thread cym13 via Digitalmars-d-learn

On Wednesday, 11 November 2015 at 16:02:07 UTC, H. S. Teoh wrote:
If performance is a problem, my first reaction would be to try 
GDC or LDC.  While there have been recent improvements in DMD 
code generation quality, it still has a ways to go to catch 
with GDC/LDC's optimizer.



T


My computer seems to agree (note that I did those a bunch of time 
with
intermediate rounds to heat the cache, these numbers are only to 
give

a rough idea):

$time rdmd --compiler=ldc test.d
|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  |
rdmd --compiler=ldc test.d  6.07s user 0.10s system 99% cpu 6.177 
total


$time rdmd --compiler=dmd test.d
|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  |
rdmd --compiler=dmd test.d  21.21s user 0.09s system 97% cpu 
21.919 total


$time ./test.pl
|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  |
./test.pl  13.71s user 0.00s system 99% cpu 13.715 total


With optimization on it is better but still not enough for dmd:


$time rdmd --compiler=ldc -inline -release -O test.d
|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  |
rdmd --compiler=ldc -inline -release -O test.d  4.99s user 0.09s 
system 98% cpu 5.170 total


$time rdmd --compiler=dmd -inline -release -O test.d
|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  |
rdmd --compiler=dmd -inline -release -O test.d  12.67s user 0.06s 
system 99% cpu 12.736 total




Re: my first D program (and benchmark against perl)

2015-11-11 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Nov 11, 2015 at 02:26:28PM +, Andrea Fontana via 
Digitalmars-d-learn wrote:
> On Wednesday, 11 November 2015 at 13:32:00 UTC, perlancar wrote:
> >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?
> 
> Did you try rdmd -O -noboundscheck -release yourscript.d ?
[...]

If performance is a problem, my first reaction would be to try GDC or
LDC.  While there have been recent improvements in DMD code generation
quality, it still has a ways to go to catch with GDC/LDC's optimizer.


T

-- 
Старый друг лучше новых двух.


Re: my first D program (and benchmark against perl)

2015-11-11 Thread Rikki Cattermole via Digitalmars-d-learn

On 12/11/15 2:31 AM, 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:

---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 < 100; 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?


I turned it into mostly using large allocations, instead of small ones.
Although I'd recommend using Appender instead of my custom functions for 
this.


Oh and for me, I got it at 2 secs, 513 ms, 397 μs, and 5 hnsecs. 
Unoptimized, using dmd.
When release mode is enabled on dmd: 1 sec, 550 ms, 838 μs, and 9 
hnsecs. So significant improvement even with dmds awful optimizer.


import std.string;
import std.stdio;

static string SPACES = " 
  ";


string fmttable(string[][] table) {
char[] res;

// column widths
int[] widths;
size_t totalSize;

if (table.length == 0) return "";

widths.length = table[0].length;

foreach(colnum; 0 .. table[0].length) {
int width = 0;
size_t count;

foreach(rownum; 0 .. table.length) {
if (table[rownum][colnum].length > width)
width = cast(int) table[rownum][colnum].length;
count += table[rownum].length;
}

totalSize += ((width + 1) * count) + 2;
widths[colnum] = width;
}

char[] buffer = new char[](totalSize);

void assignText(string toAdd) {
if (res.length < buffer.length - toAdd.length) {
} else {
buffer.length += toAdd.length;
}

res = buffer[0 .. res.length + toAdd.length];
res[$-toAdd.length .. $] = toAdd[];
}


foreach(rownum; 0 .. table.length) {
assignText("|");
foreach(colnum; 0 .. table[rownum].length) {
assignText(SPACES[0 .. widths[colnum] - 
table[rownum][colnum].length]);

assignText(table[rownum][colnum]);
assignText("|");
}
assignText("\n");
}

return cast(string)res;
}

void main() {
// tiny table (1x1)
  

my first D program (and benchmark against perl)

2015-11-11 Thread perlancar via Digitalmars-d-learn
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 < 100; 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?


Re: my first D program (and benchmark against perl)

2015-11-11 Thread Andrea Fontana via Digitalmars-d-learn

On Wednesday, 11 November 2015 at 13:32:00 UTC, perlancar wrote:
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?


Did you try rdmd -O -noboundscheck -release yourscript.d ?

You should try using appender!string rather than concatenate 
(http://dlang.org/phobos/std_array.html#.Appender) using capacity 
(http://dlang.org/phobos/std_array.html#.Appender.capacity) to 
improve performace.


You should also switch from for to foreach.

Andrea



Re: my first D program (and benchmark against perl)

2015-11-11 Thread Rikki Cattermole via Digitalmars-d-learn

On 12/11/15 3:20 AM, Rikki Cattermole wrote:

On 12/11/15 2:31 AM, 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:

---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 < 100; 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?


I turned it into mostly using large allocations, instead of small ones.
Although I'd recommend using Appender instead of my custom functions for
this.

Oh and for me, I got it at 2 secs, 513 ms, 397 μs, and 5 hnsecs.
Unoptimized, using dmd.
When release mode is enabled on dmd: 1 sec, 550 ms, 838 μs, and 9
hnsecs. So significant improvement even with dmds awful optimizer.

import std.string;
import std.stdio;

static string SPACES = "   ";

string fmttable(string[][] table) {
 char[] res;

 // column widths
 int[] widths;
 size_t totalSize;

 if (table.length == 0) return "";

 widths.length = table[0].length;

 foreach(colnum; 0 .. table[0].length) {
 int width = 0;
 size_t count;

 foreach(rownum; 0 .. table.length) {
 if (table[rownum][colnum].length > width)
 width = cast(int) table[rownum][colnum].length;
 count += table[rownum].length;
 }

 totalSize += ((width + 1) * count) + 2;
 widths[colnum] = width;
 }

 char[] buffer = new char[](totalSize);

 void assignText(string toAdd) {
 if (res.length < buffer.length - toAdd.length) {
 } else {
 buffer.length += toAdd.length;
 }

 res = buffer[0 .. res.length + toAdd.length];
 res[$-toAdd.length .. $] = toAdd[];
 }


 foreach(rownum; 0 .. table.length) {
 assignText("|");
 foreach(colnum; 0 .. table[rownum].length) {
 assignText(SPACES[0 .. widths[colnum] -
table[rownum][colnum].length]);
 assignText(table[rownum][colnum]);
 assignText("|");
 }
 assignText("\n");
 }

My first D program

2013-05-30 Thread Shriramana Sharma
Hello. I am new to D and come from some intermediate C/C++ plus some
Python programming background. I currently have DMD 2.062 installed on
my Kubuntu Raring 64-bit system.

1. Too big binary output?

OK so I wrote my first Hello World program:

#! /usr/bin/rdmd
import std.stdio ;
void main() {
writeln ( Namaste Prapancha! ) ;
}

(so I'm a bit of a Sanskrit geek...) and when I save it as namaste.d,
do chmod +x and run ./namaste.d, all is fine and I get the output.

However I am somewhat taken aback to see the file size -- 335KiB for a
simple Hello World? The equivalent C/C++ programs compiled with Clang
without any -O options produce binaries of less than 10K!

2. No filename freedom?

Next I wanted to go to another example but I like to keep my practice
files in order, so I rename namaste.d to 01-namaste.d but I get the
error:

$ dmd 01-namaste.d
01-namaste.d: Error: module 01-namaste has non-identifier characters
in filename, use module declaration instead

Huh? Now my program *name* has to be a valid identifier in the
language? So I can't have my filename contain a hyphen-minus or start
with a digit, and only something like e01_namaste.d is permitted. Why
is this?

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा


Re: My first D program

2013-05-30 Thread Regan Heath
On Thu, 30 May 2013 12:13:19 +0100, Shriramana Sharma samj...@gmail.com  
wrote:



Hello. I am new to D and come from some intermediate C/C++ plus some
Python programming background. I currently have DMD 2.062 installed on
my Kubuntu Raring 64-bit system.

1. Too big binary output?

OK so I wrote my first Hello World program:

#! /usr/bin/rdmd
import std.stdio ;
void main() {
writeln ( Namaste Prapancha! ) ;
}

(so I'm a bit of a Sanskrit geek...) and when I save it as namaste.d,
do chmod +x and run ./namaste.d, all is fine and I get the output.

However I am somewhat taken aback to see the file size -- 335KiB for a
simple Hello World? The equivalent C/C++ programs compiled with Clang
without any -O options produce binaries of less than 10K!


The D standard library is currently statically linked.  This will change  
shortly/eventually.



2. No filename freedom?

Next I wanted to go to another example but I like to keep my practice
files in order, so I rename namaste.d to 01-namaste.d but I get the
error:

$ dmd 01-namaste.d
01-namaste.d: Error: module 01-namaste has non-identifier characters
in filename, use module declaration instead

Huh? Now my program *name* has to be a valid identifier in the
language? So I can't have my filename contain a hyphen-minus or start
with a digit, and only something like e01_namaste.d is permitted. Why
is this?


As the error says use module declaration instead.  You need to add a  
module namaste; statement to the top of the file 01-namaste.d.  D  
defaults the module name to the filename, but you can specify it when they  
differ.


R

--
Using Opera's revolutionary email client: http://www.opera.com/mail/


Re: My first D program

2013-05-30 Thread bearophile

Shriramana Sharma:

However I am somewhat taken aback to see the file size -- 
335KiB for a
simple Hello World? The equivalent C/C++ programs compiled with 
Clang

without any -O options produce binaries of less than 10K!


On Windows32 DMD produces binaries for small programs that are 
often half the size of binaries generated by similar small C++ 
programs compiled with G++ (about 300+ against 700+).


D has a garbage collector, runtime type introspection (module 
info, type info, etc), run-time built-in operations on dynamic 
arrays (concat, append), associative arrays and some of their 
operations, a sort (but probably the built-in sort and reverse 
will be deprecated and later removed), exceptions, and more. All 
that needs space that's absent in the C++ binary.


---

Regan Heath:

The D standard library is currently statically linked.  This 
will change shortly/eventually.


And then you will need the GC somewhere to run it :-) Both static 
and dynamic linking have their advantages and disadvantages. I 
think Go has a storng preference for static linking.


Bye,
bearophile


Re: My first D program

2013-05-30 Thread Shriramana Sharma
Thanks to all those who kindly replied.

On Thu, May 30, 2013 at 9:57 PM, Regan Heath re...@netmail.co.nz wrote:

 The D standard library is currently statically linked.  This will change
 shortly/eventually.

Ah OK -- should have thought of that. So whatever is in libc.so or
libstdc++.so doesn't get counted to the size of the C/C++ executables.
Likewise we should have a libd.so I suppose. I am all for having
shared runtime/stdlib.

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा