January 17, 2023
On Tuesday, 17 January 2023 at 21:50:06 UTC, matheus wrote:
> Question: Have you compared the timings between this way (With ranges) and a normal way (Without ranges)?

If you are intensively using ranges, UFCS or the other convenient high level language features, then the compiler choice does matter a lot. And only LDC compiler is able to produce fast binaries from such source code.

GDC compiler has severe performance problems with inlining, unless LTO is enabled. And it also allocates closures on stack. This may or may not be fixed in the future, but today I can't recommend GDC if you really care about performance.

DMD compiler uses an outdated code generation backend from Digital Mars C++ and will never be able to produce fast binaries. It prioritizes fast compilation speed over everything else.

> I'm using D Online Compiler from different platforms but unfortunately I can't loop too much because they don't accept, but anyway a normal version runs almost twice faster than this version (With ranges).

Can you try to run the following diagnostics program on this D Online Compiler platform? https://gist.github.com/ssvb/5c926ed9bc755900fdaac3b71a0f7cfd

> If you like I could send or post here a version without ranges to try out.

Please post it. This is interesting.
January 17, 2023
On Tue, Jan 17, 2023 at 11:08:19PM +0000, Siarhei Siamashka via Digitalmars-d-learn wrote:
> On Tuesday, 17 January 2023 at 21:50:06 UTC, matheus wrote:
> > Question: Have you compared the timings between this way (With
> > ranges) and a normal way (Without ranges)?
> 
> If you are intensively using ranges, UFCS or the other convenient high level language features, then the compiler choice does matter a lot. And only LDC compiler is able to produce fast binaries from such source code.
> 
> GDC compiler has severe performance problems with inlining, unless LTO is enabled. And it also allocates closures on stack. This may or may not be fixed in the future, but today I can't recommend GDC if you really care about performance.

Interesting, I didn't know GDC has issues with inlining. I thought it was more-or-less on par with LDC in terms of the quality of code generation.  Do you have a concrete example of this problem?


> DMD compiler uses an outdated code generation backend from Digital Mars C++ and will never be able to produce fast binaries. It prioritizes fast compilation speed over everything else.
[...]

For anything performance related, I wouldn't even consider DMD. For all the 10+ years I've been using D, it has consistently produced executables that run about 20-30% slower than those produced by LDC or GDC, sometimes even up to 40%.  For script-like programs or interactive apps that don't care about performance, DMD is fine for convenience and fast compile turnaround times.  But as soon as performance matters, DMD is not even on my radar.


T

-- 
Heuristics are bug-ridden by definition. If they didn't have bugs, they'd be algorithms.
January 17, 2023
On Tuesday, 17 January 2023 at 23:08:19 UTC, Siarhei Siamashka wrote:
> On Tuesday, 17 January 2023 at 21:50:06 UTC, matheus wrote:
>> Question: Have you compared the timings between this way (With ranges) and a normal way (Without ranges)?
>
> If you are intensively using ranges, UFCS or the other convenient high level language features, then the compiler choice does matter a lot. And only LDC compiler is able to produce fast binaries from such source code.
> ...

I ran in two sites: https://onecompiler.com/d and then https://godbolt.org/, with the latter I set LDC with -O2.

My version (Source in the end) ran about 2x faster than the version with ranges.

>...
>
>> I'm using D Online Compiler from different platforms but unfortunately I can't loop too much because they don't accept, but anyway a normal version runs almost twice faster than this version (With ranges).
>
> Can you try to run the following diagnostics program on this D Online Compiler platform? https://gist.github.com/ssvb/5c926ed9bc755900fdaac3b71a0f7cfd

https://onecompiler.com/d/3yv7t9ap9

Gives me:

HelloWorld.d(43): Error: undefined identifier `volatileStore`
HelloWorld.d(44): Error: undefined identifier `volatileLoad`


>
>> If you like I could send or post here a version without ranges to try out.
>
> Please post it. This is interesting.

Like I said above I ran my version against the one with ranges (From: https://github.com/quickfur/dcal/blob/master/dcal.d), and I modified to just print the calendar for some year.

With godbolt.org LDC -O2 my version ran 2x faster, and here is the source:

import std.stdio, std.string, std.conv, std.range, std.datetime;
import std.datetime.stopwatch : benchmark, StopWatch;

void draw_months(int year ,int month, int columns){
  int i;

  if(month>12){return;}

  auto columspace = " ".replicate(columns);

  write("\n");
  for(i=0;i<columns;++i){
    if(month+i>12){break;}
    write("       " ~ " ".replicate(11*(i>0))  ~ columspace,capitalize(to!string(Date(year,month+i,1).month)));
  }

  write("\n");
  auto m = new string[][](columns);
  for(int j=0;j<columns;++j){
    if(month+j>12){return;}
    for(i=1;i<8;++i){
        write(to!string(Date(1899,1,i).dayOfWeek)[0..2], " ");
    }

    int c = DW[to!string(Date(year,month+j,1).dayOfWeek)];
    auto dm = Date(2023,month+j,1).daysInMonth;

    for(i=0;i<c;++i){ m[j] ~= " "; }
    for(i=1;i<dm+1;++i){ m[j] ~= i.to!string; }
    for(;i<36;++i){ m[j] ~= " "; }

    write(columspace);
  }

  //write("\n\n",m[0].length,"\n");
  writeln();
  for(int k=0;k<5;++k){
    for(int j=0;j<columns;++j){
      for(i=k*7;i<(k+1)*7;++i){
        writef("%2s ",m[j][i]);
      }
      write(columspace);
    }
    writeln();
  }
}

void draw_year(int year, int columns){
  int steps = 12/columns;

  for(int i=0;i<steps;++i){
    draw_months(2023,(i*columns)+1,columns);
  }
}

int[string] DW;

void main(){
    int[string] dow;
    int i, y = 2023, m = 1, d = 1;

    auto sw = StopWatch();
    sw.start();

    for(i=1;i<8;++i){
      DW[to!string(Date(1899,1,i).dayOfWeek)]=i-1;
    }

    for(i=0;i<10;++i){
      draw_year(2023,3);
    }
    sw.stop();
    writeln(sw.peek.total!"usecs");
}

Matheus.
January 18, 2023
On Tuesday, 17 January 2023 at 23:27:03 UTC, matheus wrote:
> I ran in two sites: https://onecompiler.com/d and then https://godbolt.org/, with the latter I set LDC with -O2.
>
> My version (Source in the end) ran about 2x faster than the version with ranges.

Well, the use of ranges is not the only difference.

>> Can you try to run the following diagnostics program on this D Online Compiler platform? https://gist.github.com/ssvb/5c926ed9bc755900fdaac3b71a0f7cfd
>
> https://onecompiler.com/d/3yv7t9ap9
>
> Gives me:
>
> HelloWorld.d(43): Error: undefined identifier `volatileStore`
> HelloWorld.d(44): Error: undefined identifier `volatileLoad`

The volatileStore/volatileLoad functions used to be in `core.bitop` in the old versions of D compilers, but then moved to `core.volatile`. This kind of reshuffling is annoying, because supporting multiple versions of D compilers becomes unnecessarily difficult. After importing `core.volatile` in https://onecompiler.com/d/3yv7u9v7c now it prints:

    Detected compiler: DMD
    Performance warning: '-O' option was not used!
    Performance warning: '-release' option was not used!
    Performance warning: DMD generates much slower code than GDC or LDC!

And this is a systematic problem with various online D compilers. Some of them don't bother to enable optimizations. Which isn't bad by itself, but makes it unsuitable for running benchmarks.
January 18, 2023

On Tuesday, 17 January 2023 at 21:50:06 UTC, matheus wrote:

>

Have you compared the timings between this way (With ranges) and a normal way (Without ranges)?

Of course it is possible to speed it up. However, even as it is, it is enough to see the power of intervals. I would argue that you'll get fast results even with DMD Compiler!

import std.stdio;
import std.datetime.date;

void main()
{
  import std.datetime.stopwatch : benchmark, StopWatch;
  auto sw = StopWatch();

#line 1
  sw.start();

  enum xTest = 1200;
  auto title = enumToStr!DayOfWeek(2);

  auto date = Date(2023, 12, 1);
  auto range = MyCalendar(date);
  for(size_t test; test < xTest; range.popFront, ++test)
  {
    range.writeln;             // month and year
    title.writefln!"%-(%s %)"; // days of week
    range.front.writeln;       // formatted days
  }
  sw.stop();
  writeln(sw.peek.total!"usecs");
}

struct MyCalendar
{
  import std.array  : appender, replicate;
  import std.format : format, formattedWrite;
  import std.string : capitalize;

  Date date;
  enum empty = false;

  string front()
  {
    auto res = appender!string;
    int day, dow = date.dayOfWeek;
    // skip days:
    res.formattedWrite("%s", " ".replicate(dow * 3));

    for(day = 1; day <= date.daysInMonth; ++day)
    {
      res.formattedWrite("%2s ", day);
      if(++dow % 7 == 0) res.put("\n");
    }
    if(dow % 7) res.put("\n");
    return res.data;
  }

  void popFront()
  {
    date.roll!"months"(1);
  }

  string toString() const
  {
    const currentYear = date.year;   // Current Year
    const currentMonth = date.month; // Name of the month
    const monthAndYear = format("%s/%s:",
                            currentMonth,
                            currentYear);
    return capitalize(monthAndYear);
  }
}

auto enumToStr(E)(size_t len = 0)
{
  import std.conv : to;
  string[] result;
  for(E x = E.min; x <= E.max; x++)
  {
    result ~= len ? x.to!string[0..len]
                  : x.to!string;
  }
  return result;
}

SDB@79

January 18, 2023
On Wednesday, 18 January 2023 at 01:05:58 UTC, Siarhei Siamashka wrote:
> On Tuesday, 17 January 2023 at 23:27:03 UTC, matheus wrote:
>> I ran in two sites: https://onecompiler.com/d and then https://godbolt.org/, with the latter I set LDC with -O2.
>>
>> My version (Source in the end) ran about 2x faster than the version with ranges.
>
> Well, the use of ranges is not the only difference.
> ...

What are the other differences?

Just remember what I said above:

> I ran my version against the one with ranges (From: https://github.com/quickfur/dcal/blob/master/dcal.d), and I modified to just print the calendar for some year.

Again I ran both versions with/without ranges only generating and printing the months.

Matheus.
January 18, 2023
On Wednesday, 18 January 2023 at 04:51:11 UTC, Salih Dincer wrote:
> On Tuesday, 17 January 2023 at 21:50:06 UTC, matheus wrote:
>> Have you compared the timings between this way (With ranges) and a normal way (Without ranges)?
>
> Of course it is possible to speed it up.  However, even as it is, it is enough to see the power of intervals.  I would argue that you'll get fast results even with DMD Compiler!
>
> ```d
> ...

Well I'll need to check this, because your version is slightly different than mine and this one (https://github.com/quickfur/dcal/blob/master/dcal.d), It prints only one column. I'll change mine to do this and compare, I can't do this right now because I'm at work.

But unfortunately I can't use xTest = 1200 on these online compilers, only 10 or they will stop.

Could you please run your version vs mine (Changing to print one column, line 70: draw_year(2023,1); ) and tell us the result?

Matheus.
January 19, 2023
On Wednesday, 18 January 2023 at 11:10:01 UTC, matheus wrote:
> On Wednesday, 18 January 2023 at 01:05:58 UTC, Siarhei Siamashka wrote:
>> On Tuesday, 17 January 2023 at 23:27:03 UTC, matheus wrote:
>>> I ran in two sites: https://onecompiler.com/d and then https://godbolt.org/, with the latter I set LDC with -O2.
>>>
>>> My version (Source in the end) ran about 2x faster than the version with ranges.
>>
>> Well, the use of ranges is not the only difference.
>> ...
>
> What are the other differences?

Can't you easily see them yourself? For example, the https://github.com/quickfur/dcal/blob/master/dcal.d implementation uses https://dlang.org/library/std/format/format.html but I don't see it in your code. And this is not the only difference. Your code even doesn't produce the same output.

> Just remember what I said above:
>
>> I ran my version against the one with ranges (From: https://github.com/quickfur/dcal/blob/master/dcal.d), and I modified to just print the calendar for some year.
>
> Again I ran both versions with/without ranges only generating and printing the months.

You are comparing two completely different implementations. If you wanted to specifically measure the overhead of using ranges, then you could just remove them without changing how the std.datetime api calls are done and how strings are formatted.
January 19, 2023

On Wednesday, 18 January 2023 at 11:20:11 UTC, matheus wrote:

>

Could you please run your version vs mine (Changing to print one column, line 70: draw_year(2023,1); ) and tell us the result?

When implementing MyCalendar(), it was not designed to output multiple columns. Therefore, we cannot make a direct comparison. But the code you designed is also very nice. Can you let me do a little magic touch using contract programming?

void draw_year(int columns)(int year)
in(imported!"std.numeric".lcm(12, columns) == 12, "Permited columns < 4, 6 and 12") {
  foreach(i; 0..12 / columns)
    year.draw_months(i * columns + 1, columns);
}
unittest
{
    //foreach(_; 0..10)
      2023.draw_year!12; // 12 x 1
      2023.draw_year!6;  //  6 x 2
      2023.draw_year!4;  //  4 x 3
      2023.draw_year!3;  //  3 x 4
      2023.draw_year!2;  //  2 x 6
      2023.draw_year!1;  //  1 x 12
}

SDB@79

1 2 3 4
Next ›   Last »