April 24, 2020
On Thursday, 23 April 2020 at 00:00:29 UTC, mipri wrote:
> On Wednesday, 22 April 2020 at 14:00:10 UTC, serge wrote:
>> My understanding that D is the language in similar ballpark performance league as C, C++, Rust. Hence the question - why web performance of those 2 web frameworks is so poor compared to rivals?
>
> Consider this benchmark from the thread next door, "Memory
> issues. GC not giving back memory to OS?":
>
>   import std.stdio;
>
>   void main(string[] args)
>   {
>       int[] v = [1, 2];
>       int n = 1 << 30;
>       for (int i = 0; i < n - 2; ++i)
>       {
>           v ~= i;
>       }
>       writefln("v len: %s cap: %s\n", v.length, v.capacity);
>   }
>
> With an average of four runs, compiled with gdc -O3, this takes
> 40s and has a max RSS of 7.9 GB.
>
> Here's the same benchmark changed to use std.container.array:
>
>   void main() @nogc {
>       import core.stdc.stdio : printf;
>       import std.container.array;
>
>       Array!int v = Array!int(1, 2);
>       foreach (i; 0 .. (1 << 30) - 2)
>           v ~= i;
>       printf("v len: %d cap: %d\n", v.length, v.capacity);
>   }
>
> Same treatment: 3.3s and a max RSS of 4.01 GB.
> More than ten times faster.
>
> If you set out to make a similar benchmark in C++ or Rust
> you'll naturally see performance more like the second example
> than the first. So there's some extra tension here: D has
> high-convenience facilities like this that let it compete with
> scripting languages for ease of development, but after you've
> exercised some ease of development you might want to transition
> away from these facilities.
>
> D has other tensions, like "would you like the GC, or no?" or
> "would you like the the whole language with TypeInfo and AAs,
> or no?", or "would you like speed-of-light compile times, or
> would you like to do a lot of CTFE and static reflection?"
>
> And this is more how I'd characterize the language. Not as "it
> has this such-and-such performance ballpark and I should be
> very surprised if a particular web framework doesn't match
> that", but "it's a bunch of sublanguages in one and therefore
> you have to look closer at a given web framework to even say
> which sublanguage it's written in".
>
> I think the disadvantages of D being like this are obvious. An
> advantage of it being like this, is that if you one day decide
> that you'd prefer a D application have C++-style performance,
> you don't have to laboriously rewrite the application into
> a completely different language. The D-to-D FFI, as it were, is
> really good, so you can make transitions like that as needed,
> even to just the parts of the application that need them.

I did check the library.. My understanding that proposal is to use the library with manual memory management without  GC. My concern was that D web frameworks performed worse then frameworks in Go and Java which are GC only languages.

Does it mean that GC in D is far from great that we need to avoid it in order to beat Java/Go? Probably would worth to stress  - I didn't mean in fact beat, I would love to see stats on par with Go and Java but unfortunately D was few times slower - close to Python and Ruby...
Despite the library can speed things up I believe the language/runtime should be able to work efficiently for such type of operations. We should not need to develop such libraries in order to have good performance. To me it is bug or poor implementation of GC or deficiency in design of runtime.  The need for that type of libraries to solve deficiencies in runtime would not allow to focus on writing good code but instead to look for gotchas to get adequate solution.


April 24, 2020
On Wednesday, 22 April 2020 at 14:00:10 UTC, serge wrote:
> D has sparked my interested therefore last week I have started to look into the language and have completed D course on pluralsight. One of area where I would like to apply D in  web application/cloud. Golang  is not bad but I think D seems more powerful. Although during my research I have found interesting facts:
>
> 1) fib test (https://github.com/drujensen/fib) with D  (compiled with ldc) showed really good performance results.
> 2) Various Web performance test on  https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=query show pretty poor performance of D using vibe.d and hunt framework/libraries.  Regardless of type of test - json, single query, multiple query and so on.
>
> My understanding that D is the language in similar ballpark performance league as C, C++, Rust. Hence the question - why web performance of those 2 web frameworks is so poor compared to rivals? I would say few times worse. This is not a troll post by any means. I am researching if D and D web framework whether it can be used as  replacement python/django/flask within our company. Although if D web framework show worse performance than Go then probably it is not right tool for the job.
> Any comments and feedback would be appreciated.

I gave a talk at DConf 2018 you may be interested in. The talk goes over a set of benchmark studies I did. The video was lost, but the slides are here: https://github.com/eBay/tsv-utils/blob/master/docs/dconf2018.pdf.

The slides are probably the easiest way to get an overview. The full details on the benchmark studies on the tsv-utils repo: https://github.com/eBay/tsv-utils/blob/master/docs/Performance.md

--Jon
April 24, 2020
On Thursday, 23 April 2020 at 15:57:01 UTC, drug wrote:
> And your statement that Rust assembly output is better is wrong.

https://godbolt.org/z/g_euiT

D:

    int foo(ref int a, ref int b) {
        a = 0;
        b = 1;
        return a;
    }

int example.foo(ref int, ref int):
        movl    $0, (%rsi)
        movl    $1, (%rdi)
        movl    (%rsi), %eax
        retq

Rust:

    pub fn foo(x: &mut i32, y: &mut i32) -> i32 {
        *x = 0;
        *y = 1;
        *x
    }

example::foo:
        mov     dword ptr [rdi], 0
        mov     dword ptr [rsi], 1
        xor     eax, eax
        ret


There most definitely is a difference and the assembly generated with rust is better. This is just a simple example to illustrate the difference. If you don't know why the difference is significant or why it is happening. There are a lot of great articles out there, sadly there are people such as yourself spreading misinformation that don't know what a borrow checker is and don't know Rust or why it is has gone as far as it has. This is why the borrow checker for D is going to fail. Because the person designing it, such as yourself, doesn't have any idea what they are redoing and have never even bothered to touch Rust or learn about it. Anyways I'm not your babysitter, if you don't understand the above, as most people seem to not bother to learn assembly anymore, you're on your own.





April 24, 2020
On Friday, 24 April 2020 at 19:27:40 UTC, Arine wrote:
>
> https://godbolt.org/z/g_euiT
>
> D:
>
>     int foo(ref int a, ref int b) {
>         a = 0;
>         b = 1;
>         return a;
>     }
>
> int example.foo(ref int, ref int):
>         movl    $0, (%rsi)
>         movl    $1, (%rdi)
>         movl    (%rsi), %eax
>         retq
>
> Rust:
>
>     pub fn foo(x: &mut i32, y: &mut i32) -> i32 {
>         *x = 0;
>         *y = 1;
>         *x
>     }
>
> example::foo:
>         mov     dword ptr [rdi], 0
>         mov     dword ptr [rsi], 1
>         xor     eax, eax
>         ret
>
>

Would DIP 1000 enable such optimization possibility in D?


April 24, 2020
On Friday, 24 April 2020 at 22:52:31 UTC, IGotD- wrote:
> On Friday, 24 April 2020 at 19:27:40 UTC, Arine wrote:
>>
>> https://godbolt.org/z/g_euiT
>>
>> D:
>>
>>     int foo(ref int a, ref int b) {
>>         a = 0;
>>         b = 1;
>>         return a;
>>     }
>>
>> int example.foo(ref int, ref int):
>>         movl    $0, (%rsi)
>>         movl    $1, (%rdi)
>>         movl    (%rsi), %eax
>>         retq
>>
>> Rust:
>>
>>     pub fn foo(x: &mut i32, y: &mut i32) -> i32 {
>>         *x = 0;
>>         *y = 1;
>>         *x
>>     }
>>
>> example::foo:
>>         mov     dword ptr [rdi], 0
>>         mov     dword ptr [rsi], 1
>>         xor     eax, eax
>>         ret
>>
>>
>
> Would DIP 1000 enable such optimization possibility in D?

Technically DIP 1021 could.
April 24, 2020
On Friday, 24 April 2020 at 23:03:25 UTC, Les De Ridder wrote:
> On Friday, 24 April 2020 at 22:52:31 UTC, IGotD- wrote:
>> On Friday, 24 April 2020 at 19:27:40 UTC, Arine wrote:
>>> [...]
>>
>> Would DIP 1000 enable such optimization possibility in D?
>
> Technically DIP 1021 could.

Actually, nevermind:

https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1021.md#limitations
April 24, 2020
On Friday, 24 April 2020 at 19:27:40 UTC, Arine wrote:
> Rust:
>
>     pub fn foo(x: &mut i32, y: &mut i32) -> i32 {
>         *x = 0;
>         *y = 1;
>         *x
>     }
>
> example::foo:
>         mov     dword ptr [rdi], 0
>         mov     dword ptr [rsi], 1
>         xor     eax, eax
>         ret

eh, this isn't Rust; it's "Rust +nightly with an unstable codegen flag."

Marginal codegen improvements aren't going to turn heavy usage of
dynamic arrays into heavy usage of std.container.array either, so
they're not that relevant to expected performance of real-world
programs in D vs. other languages.

April 25, 2020
On Friday, 24 April 2020 at 23:24:49 UTC, mipri wrote:
> On Friday, 24 April 2020 at 19:27:40 UTC, Arine wrote:
>> Rust:
>>
>>     pub fn foo(x: &mut i32, y: &mut i32) -> i32 {
>>         *x = 0;
>>         *y = 1;
>>         *x
>>     }
>>
>> example::foo:
>>         mov     dword ptr [rdi], 0
>>         mov     dword ptr [rsi], 1
>>         xor     eax, eax
>>         ret
>
> eh, this isn't Rust; it's "Rust +nightly with an unstable codegen flag."
>
> Marginal codegen improvements aren't going to turn heavy usage of
> dynamic arrays into heavy usage of std.container.array either, so
> they're not that relevant to expected performance of real-world
> programs in D vs. other languages.

I believe that "-enable-scoped-noalias=true" should be the D equivalent (with LDC) but it didnt change anything.
Also u can achieve the same asm with @llvmAttr("noalias") in front of at least one argument.
April 25, 2020
On Friday, 24 April 2020 at 13:58:53 UTC, serge wrote:
> On Thursday, 23 April 2020 at 00:00:29 UTC, mipri wrote:
>> On Wednesday, 22 April 2020 at 14:00:10 UTC, serge wrote:
>>> My understanding that D is the language in similar ballpark performance league as C, C++, Rust. Hence the question - why web performance of those 2 web frameworks is so poor compared to rivals?
>>
>> Consider this benchmark from the thread next door, "Memory
>> issues. GC not giving back memory to OS?":
>>
>>   import std.stdio;
>>
>>   void main(string[] args)
>>   {
>>       int[] v = [1, 2];
>>       int n = 1 << 30;
>>       for (int i = 0; i < n - 2; ++i)
>>       {
>>           v ~= i;
>>       }
>>       writefln("v len: %s cap: %s\n", v.length, v.capacity);
>>   }
>>
>> With an average of four runs, compiled with gdc -O3, this takes
>> 40s and has a max RSS of 7.9 GB.
>>
>> Here's the same benchmark changed to use std.container.array:
>>
>>   void main() @nogc {
>>       import core.stdc.stdio : printf;
>>       import std.container.array;
>>
>>       Array!int v = Array!int(1, 2);
>>       foreach (i; 0 .. (1 << 30) - 2)
>>           v ~= i;
>>       printf("v len: %d cap: %d\n", v.length, v.capacity);
>>   }
>>
>> Same treatment: 3.3s and a max RSS of 4.01 GB.
>> More than ten times faster.
>>
>> If you set out to make a similar benchmark in C++ or Rust
>> you'll naturally see performance more like the second example
>> than the first. So there's some extra tension here: D has
>> high-convenience facilities like this that let it compete with
>> scripting languages for ease of development, but after you've
>> exercised some ease of development you might want to transition
>> away from these facilities.
>>
>> D has other tensions, like "would you like the GC, or no?" or
>> "would you like the the whole language with TypeInfo and AAs,
>> or no?", or "would you like speed-of-light compile times, or
>> would you like to do a lot of CTFE and static reflection?"
>>
>> And this is more how I'd characterize the language. Not as "it
>> has this such-and-such performance ballpark and I should be
>> very surprised if a particular web framework doesn't match
>> that", but "it's a bunch of sublanguages in one and therefore
>> you have to look closer at a given web framework to even say
>> which sublanguage it's written in".
>>
>> I think the disadvantages of D being like this are obvious. An
>> advantage of it being like this, is that if you one day decide
>> that you'd prefer a D application have C++-style performance,
>> you don't have to laboriously rewrite the application into
>> a completely different language. The D-to-D FFI, as it were, is
>> really good, so you can make transitions like that as needed,
>> even to just the parts of the application that need them.
>
> I did check the library.. My understanding that proposal is to use the library with manual memory management without  GC. My concern was that D web frameworks performed worse then frameworks in Go and Java which are GC only languages.
>
> Does it mean that GC in D is far from great that we need to avoid it in order to beat Java/Go? Probably would worth to stress  - I didn't mean in fact beat, I would love to see stats on par with Go and Java but unfortunately D was few times slower - close to Python and Ruby...
> Despite the library can speed things up I believe the language/runtime should be able to work efficiently for such type of operations. We should not need to develop such libraries in order to have good performance. To me it is bug or poor implementation of GC or deficiency in design of runtime.  The need for that type of libraries to solve deficiencies in runtime would not allow to focus on writing good code but instead to look for gotchas to get adequate solution.

Yes, that does mean that D's GC still needs some improvements, although much have been done during the last year.

Also note that while Java and Go are heavy GC languages, there are ways to do value based coding, and although Project Valhala is taking its time due to the engineering issues it addresses, it will eventually be done.

Just like in all GC enabled languages that offer multiple allocation mechanisms alongside the GC you should approach it in stages.

Use the GC for you initial solution and only in cases where it is obvious from the start that it might be a problem, or when proven that some issues might have to be adressed then look for value allocation, @nogc, referenced counted collections and other low level style tricks.

That is the nice thing about systems languages like D, you don't need to code like C from the start, and when you need to actually do it, the tools are available.


April 25, 2020
On Wednesday, 22 April 2020 at 14:00:10 UTC, serge wrote:
> 2) Various Web performance test on  https://www.techempower.com/benchmarks/#section=data-r18&hw=ph&test=query show pretty poor performance of D using vibe.d and hunt framework/libraries.  Regardless of type of test - json, single query, multiple query and so on.

I don't have a reference off the top of my head, but IIRC much of the upper end of those benchmarks is the result less of inherent language or framework differences and more to do with which implementations have been strongly tailored for each particular benchmark.  (I think this has been discussed on the D forums before.)

That tailoring to the benchmark often means dropping things (e.g. certain kinds of validation or safety measures) that any realistic app would have to do.  So the top end of those benchmark tables may be rather misleading when it comes to real-world usage.

There may well be framework design decisions in place that have a stronger impact.  For example I recall that the default "user-friendly" vibe.d tools for handling HTTP requests creates a situation where the easy thing to do is generate garbage per request.  So unless one addresses that, it will put ready constraints on exactly how performant one can get.

Note, this is _not_ a case of "the GC is bad" or "you can't get good performance with a GC".  It's a case of, if you use the GC naively, rather than having a good strategy for preallocation and re-use of resources, you will force the GC into having to do work that can be avoided.

So leaving aside misleading factors like extreme tailoring to the benchmark, I would suggest the memory allocation strategies in use are probably the first thing to look at in asking why those D implementations might be less performant could than they could be.

When it comes to the frameworks, the questions might be: (i) are there any cases where that framework _forces_ you into a suboptimal memory (re)allocation strategy? and (ii) even if there aren't, how easy/idiomatic is it to use a performance-oriented allocation strategy?