Jump to page: 1 26  
Page
Thread overview
D compiles fast, right? Right??
Mar 30, 2018
Atila Neves
Mar 30, 2018
Meta
Mar 30, 2018
Jonathan Marler
Apr 02, 2018
Atila Neves
Apr 02, 2018
Seb
Apr 02, 2018
Jonathan Marler
Apr 02, 2018
Jonathan M Davis
Apr 03, 2018
Atila Neves
Apr 03, 2018
H. S. Teoh
Apr 03, 2018
Jonathan Marler
Apr 03, 2018
Rubn
Apr 03, 2018
bachmeier
Apr 03, 2018
Atila Neves
Apr 04, 2018
Jonathan M Davis
Apr 04, 2018
Stefan Koch
Apr 04, 2018
Dmitry Olshansky
Apr 04, 2018
Stefan Koch
Apr 04, 2018
Jack Stouffer
Apr 04, 2018
Stefan Koch
Apr 04, 2018
Jack Stouffer
Apr 04, 2018
Jonathan Marler
Apr 04, 2018
H. S. Teoh
Apr 03, 2018
burjui
Apr 03, 2018
H. S. Teoh
Apr 03, 2018
Atila Neves
Apr 04, 2018
Jonathan Marler
Apr 02, 2018
H. S. Teoh
Apr 02, 2018
Jonathan M Davis
Apr 02, 2018
Jonathan M Davis
Mar 30, 2018
bachmeier
Mar 30, 2018
Stefan Koch
Mar 30, 2018
Seb
Mar 31, 2018
Jonathan Marler
Mar 31, 2018
Jonathan M Davis
Apr 01, 2018
Jonathan Marler
Apr 01, 2018
Jonathan M Davis
Apr 01, 2018
Walter Bright
Apr 01, 2018
Stefan Koch
Apr 02, 2018
Atila Neves
Apr 02, 2018
Stefan Koch
Apr 02, 2018
H. S. Teoh
Apr 02, 2018
H. S. Teoh
Apr 02, 2018
Seb
Apr 03, 2018
Stefan Koch
Mar 30, 2018
Seb
Apr 03, 2018
Kagamin
Apr 03, 2018
Atila Neves
Apr 03, 2018
H. S. Teoh
Apr 04, 2018
Marco Leise
Apr 04, 2018
Jonathan M Davis
March 30, 2018
Fast code fast, they said. It'll be fun, they said. Here's a D file:

    import std.path;


Yep, that's all there is to it. Let's compile it on my laptop:

    /tmp % time dmd -c  foo.d
    dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total


That... doesn't seem too fast to me. But wait, there's more:

    /tmp % time dmd -c -unittest foo.d
    dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total


Half. A. Second. AKA "an eternity" in dog years, err, CPU time. I know this has been brought up before, and recently even, but, just... just... sigh.

So I wondered how fast it'd be in Go, since it's got a reputation for speedy compilation:

    package foo
    import "path"
    func Foo() string {
	    return path.Base("foo")
    }

    /tmp % time go tool compile foo.go
    go tool compile foo.go  0.01s user 0.01s system 117% cpu 0.012 total


See, now that's what I'd consider fast. It has actual code in the file because otherwise it complains the file isn't using the imported package, because, Go things. It compiled so fast I had to check I'd generated an object file, and then I learned you can't use objdump on Go .o files, because... more Go things (go tool objdump for the curious).

Ok, so how about C++, surely that will make D look good?

    #include <experimental/filesystem>  // yes, also a one-liner

    /tmp % time /usr/bin/clang++ -std=c++17 -c foo.cpp
    /usr/bin/clang++ -std=c++17 -c foo.cpp  0.45s user 0.03s system 96% cpu 0.494 total

    /tmp % time /usr/bin/g++ -std=c++17 -c foo.cpp
    /usr/bin/g++ -std=c++17 -c foo.cpp  0.39s user 0.04s system 99% cpu 0.429 total


So.... yeeaaaaaaaaah. If one is compiling unit tests, which I happen to pretty much only exclusively do, then trying to do anything with paths in D is

1. Comparable to C++ in build times
2. Actually _slower_ than C++ (who'd've thunk it?) *
3. Gets lapped around Captain America vs The Falcon style about 50 times by Go.

And that's assuming there's a crazy D programmer out there (hint: me) that actually tries to compile minimal units at a time (with actual dependency tracking!) instead of the whole project at once, otherwise it'll take even longer. And this to just import `std.path`, then there's the actual work you were trying to get to.

Today actually made me want to write Go. I'm going to take a shower now.

Atila

* Building a whole project in C++ still takes a lot longer since D scales much better, but that's not my typical worflow, nor should it be anyone else's.
March 30, 2018
On Friday, 30 March 2018 at 16:12:44 UTC, Atila Neves wrote:
> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>
>     import std.path;
>
>
> Yep, that's all there is to it. Let's compile it on my laptop:
>
>     /tmp % time dmd -c  foo.d
>     dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>
>
> That... doesn't seem too fast to me. But wait, there's more:
>
>     /tmp % time dmd -c -unittest foo.d
>     dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>
>
> Half. A. Second. AKA "an eternity" in dog years, err, CPU time. I know this has been brought up before, and recently even, but, just... just... sigh.
>
> So I wondered how fast it'd be in Go, since it's got a reputation for speedy compilation:
>
>     package foo
>     import "path"
>     func Foo() string {
> 	    return path.Base("foo")
>     }
>
>     /tmp % time go tool compile foo.go
>     go tool compile foo.go  0.01s user 0.01s system 117% cpu 0.012 total
>
>
> See, now that's what I'd consider fast. It has actual code in the file because otherwise it complains the file isn't using the imported package, because, Go things. It compiled so fast I had to check I'd generated an object file, and then I learned you can't use objdump on Go .o files, because... more Go things (go tool objdump for the curious).
>
> Ok, so how about C++, surely that will make D look good?
>
>     #include <experimental/filesystem>  // yes, also a one-liner
>
>     /tmp % time /usr/bin/clang++ -std=c++17 -c foo.cpp
>     /usr/bin/clang++ -std=c++17 -c foo.cpp  0.45s user 0.03s system 96% cpu 0.494 total
>
>     /tmp % time /usr/bin/g++ -std=c++17 -c foo.cpp
>     /usr/bin/g++ -std=c++17 -c foo.cpp  0.39s user 0.04s system 99% cpu 0.429 total
>
>
> So.... yeeaaaaaaaaah. If one is compiling unit tests, which I happen to pretty much only exclusively do, then trying to do anything with paths in D is
>
> 1. Comparable to C++ in build times
> 2. Actually _slower_ than C++ (who'd've thunk it?) *
> 3. Gets lapped around Captain America vs The Falcon style about 50 times by Go.
>
> And that's assuming there's a crazy D programmer out there (hint: me) that actually tries to compile minimal units at a time (with actual dependency tracking!) instead of the whole project at once, otherwise it'll take even longer. And this to just import `std.path`, then there's the actual work you were trying to get to.
>
> Today actually made me want to write Go. I'm going to take a shower now.
>
> Atila
>
> * Building a whole project in C++ still takes a lot longer since D scales much better, but that's not my typical worflow, nor should it be anyone else's.

Yeah, that's pretty bad, relatively, for a no-op build. Probably some CTFE or template stuff that gets pulled in by one of the imports.
March 30, 2018
On Friday, 30 March 2018 at 16:12:44 UTC, Atila Neves wrote:
> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>
>     import std.path;
>
>
> Yep, that's all there is to it. Let's compile it on my laptop:
>
>     /tmp % time dmd -c  foo.d
>     dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>
>
> That... doesn't seem too fast to me. But wait, there's more:
>
>     /tmp % time dmd -c -unittest foo.d
>     dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>
>
> Half. A. Second. AKA "an eternity" in dog years, err, CPU time. I know this has been brought up before, and recently even, but, just... just... sigh.
>
> So I wondered how fast it'd be in Go, since it's got a reputation for speedy compilation:
>
>     package foo
>     import "path"
>     func Foo() string {
> 	    return path.Base("foo")
>     }
>
>     /tmp % time go tool compile foo.go
>     go tool compile foo.go  0.01s user 0.01s system 117% cpu 0.012 total
>
>
> See, now that's what I'd consider fast. It has actual code in the file because otherwise it complains the file isn't using the imported package, because, Go things. It compiled so fast I had to check I'd generated an object file, and then I learned you can't use objdump on Go .o files, because... more Go things (go tool objdump for the curious).
>
> Ok, so how about C++, surely that will make D look good?
>
>     #include <experimental/filesystem>  // yes, also a one-liner
>
>     /tmp % time /usr/bin/clang++ -std=c++17 -c foo.cpp
>     /usr/bin/clang++ -std=c++17 -c foo.cpp  0.45s user 0.03s system 96% cpu 0.494 total
>
>     /tmp % time /usr/bin/g++ -std=c++17 -c foo.cpp
>     /usr/bin/g++ -std=c++17 -c foo.cpp  0.39s user 0.04s system 99% cpu 0.429 total
>
>
> So.... yeeaaaaaaaaah. If one is compiling unit tests, which I happen to pretty much only exclusively do, then trying to do anything with paths in D is
>
> 1. Comparable to C++ in build times
> 2. Actually _slower_ than C++ (who'd've thunk it?) *
> 3. Gets lapped around Captain America vs The Falcon style about 50 times by Go.
>
> And that's assuming there's a crazy D programmer out there (hint: me) that actually tries to compile minimal units at a time (with actual dependency tracking!) instead of the whole project at once, otherwise it'll take even longer. And this to just import `std.path`, then there's the actual work you were trying to get to.
>
> Today actually made me want to write Go. I'm going to take a shower now.
>
> Atila
>
> * Building a whole project in C++ still takes a lot longer since D scales much better, but that's not my typical worflow, nor should it be anyone else's.

Seems like you're comparing apples to oranges.

Go's path.go is very small, a 215 line file:
https://github.com/golang/go/blob/master/src/path/path.go
Documentation: https://golang.org/pkg/path/


Dlang's std.path is much more comprehensive with 4181 lines: https://github.com/dlang/phobos/blob/master/std/path.d
Documentation: https://dlang.org/phobos/std_path.html

It's over an order of magnitude more code and only takes twice as long to compile without unittests, and it's only fair to compare the "non-unittest" version of std.path with Go, since Go does not include unittests.

I'm not sure why you would compile the standard library unittests every time you compile anything. Probably a consequence of not having `-unittest=<pattern>`.  timotheecour suggested we add support for this and I agree for cases like this, where druntime and phobos would be exclude by default (just like we do with -i), meaning that your compilation example would not have compiled phobos unittests.

March 30, 2018
On Friday, 30 March 2018 at 16:12:44 UTC, Atila Neves wrote:

>     /tmp % time dmd -c  foo.d
>     dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>
>
> That... doesn't seem too fast to me. But wait, there's more:
>
>     /tmp % time dmd -c -unittest foo.d
>     dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>

I did the same timings on my computer, and I got 0.128s and 0.272s. I'm on DMD 2.075.1, so something must have changed in std.path since then.

March 30, 2018
On 3/30/18 12:12 PM, Atila Neves wrote:
> Fast code fast, they said. It'll be fun, they said. Here's a D file:
> 
>      import std.path;
> 
> 
> Yep, that's all there is to it. Let's compile it on my laptop:
> 
>      /tmp % time dmd -c  foo.d
>      dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total

Could be faster.

> That... doesn't seem too fast to me. But wait, there's more:
> 
>      /tmp % time dmd -c -unittest foo.d
>      dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total

Not fast. We need to make -unittest only affect the built module. Even though it breaks certain uses of __traits(getUnittests). No two ways about it. Who can work on that?

Andrei
March 30, 2018
On Friday, 30 March 2018 at 16:12:44 UTC, Atila Neves wrote:
> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>
>     import std.path;
>
>
> Yep, that's all there is to it. Let's compile it on my laptop:
>
>     /tmp % time dmd -c  foo.d
>     dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total

We had a recent discussion about this:

https://github.com/dlang/phobos/pull/5916

tl;dr:
- e.g. all unicode tables are probably imported and CTFE-ed (that's a huge chunk)
- Vladimir has written an excellent tool (-> https://github.com/CyberShadow/DBuildStat)
March 30, 2018
On Friday, 30 March 2018 at 20:17:39 UTC, Andrei Alexandrescu wrote:
> On 3/30/18 12:12 PM, Atila Neves wrote:
>> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>> 
>>      import std.path;
>> 
>> 
>> Yep, that's all there is to it. Let's compile it on my laptop:
>> 
>>      /tmp % time dmd -c  foo.d
>>      dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>
> Could be faster.
>
>> That... doesn't seem too fast to me. But wait, there's more:
>> 
>>      /tmp % time dmd -c -unittest foo.d
>>      dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>
> Not fast. We need to make -unittest only affect the built module. Even though it breaks certain uses of __traits(getUnittests). No two ways about it. Who can work on that?
>
> Andrei

unittests by nature usually have a short list of dependencies and therefore their compilation can be parallelized.
There are many performance leaks we can fix, before we need to think about breaking useful features!
March 30, 2018
On Friday, 30 March 2018 at 20:40:16 UTC, Stefan Koch wrote:
> On Friday, 30 March 2018 at 20:17:39 UTC, Andrei Alexandrescu wrote:
>> On 3/30/18 12:12 PM, Atila Neves wrote:
>>> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>>> 
>>>      import std.path;
>>> 
>>> 
>>> Yep, that's all there is to it. Let's compile it on my laptop:
>>> 
>>>      /tmp % time dmd -c  foo.d
>>>      dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>>
>> Could be faster.
>>
>>> That... doesn't seem too fast to me. But wait, there's more:
>>> 
>>>      /tmp % time dmd -c -unittest foo.d
>>>      dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>>
>> Not fast. We need to make -unittest only affect the built module. Even though it breaks certain uses of __traits(getUnittests). No two ways about it. Who can work on that?
>>
>> Andrei
>
> unittests by nature usually have a short list of dependencies and therefore their compilation can be parallelized.
> There are many performance leaks we can fix, before we need to think about breaking useful features!

No one wants to run the std.regex's testsuite when they pass -unittest or instantiate and run all tests for all Tuple combinations present.
If you can make dmd so fast that this happens unnoticed, that would be amazing, otherwise I suggest we don't run Phobos's templated unittests in user-code.
March 31, 2018
On Friday, 30 March 2018 at 20:17:39 UTC, Andrei Alexandrescu wrote:
> On 3/30/18 12:12 PM, Atila Neves wrote:
>> Fast code fast, they said. It'll be fun, they said. Here's a D file:
>> 
>>      import std.path;
>> 
>> 
>> Yep, that's all there is to it. Let's compile it on my laptop:
>> 
>>      /tmp % time dmd -c  foo.d
>>      dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
>
> Could be faster.
>
>> That... doesn't seem too fast to me. But wait, there's more:
>> 
>>      /tmp % time dmd -c -unittest foo.d
>>      dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu 0.525 total
>
> Not fast. We need to make -unittest only affect the built module. Even though it breaks certain uses of __traits(getUnittests). No two ways about it. Who can work on that?
>
> Andrei

If you approve of the -unittest=<pattern> approach then timotheecour has already offered to implement this.  It's pattern matching would work the same as -i and would also use the "implied standard exclusions" that -i uses, namely,

-unittest=-std -unittest=-etc -unittest=-core

This would mean that by default, just passing "-unittest" would exclude druntime/phobos just like "-i" by itself also does.
March 31, 2018
On Saturday, March 31, 2018 08:28:31 Jonathan Marler via Digitalmars-d wrote:
> On Friday, 30 March 2018 at 20:17:39 UTC, Andrei Alexandrescu
>
> wrote:
> > On 3/30/18 12:12 PM, Atila Neves wrote:
> >> Fast code fast, they said. It'll be fun, they said. Here's a D
> >>
> >> file:
> >>      import std.path;
> >>
> >> Yep, that's all there is to it. Let's compile it on my laptop:
> >>      /tmp % time dmd -c  foo.d
> >>      dmd -c foo.d  0.12s user 0.02s system 98% cpu 0.139 total
> >
> > Could be faster.
> >
> >> That... doesn't seem too fast to me. But wait, there's more:
> >>      /tmp % time dmd -c -unittest foo.d
> >>      dmd -c -unittest foo.d  0.46s user 0.06s system 99% cpu
> >>
> >> 0.525 total
> >
> > Not fast. We need to make -unittest only affect the built module. Even though it breaks certain uses of __traits(getUnittests). No two ways about it. Who can work on that?
> >
> > Andrei
>
> If you approve of the -unittest=<pattern> approach then timotheecour has already offered to implement this.  It's pattern matching would work the same as -i and would also use the "implied standard exclusions" that -i uses, namely,
>
> -unittest=-std -unittest=-etc -unittest=-core
>
> This would mean that by default, just passing "-unittest" would exclude druntime/phobos just like "-i" by itself also does.

And every time you used another library, you'd have the same problem and have to add -unittest=- whatever for each and every one of them, or you would have to use -unittest= with everything from your application or library rather than using -unittest. I really don't see how that scales well, and it's way too manual and too easy to screw up. It might be a decent idea for a workaround, but it's not a great solution.

IMHO, this is really something that should be handled by the compiler. It simply shouldn't be compiling in the unittest blocks for modules that you're not compiling directly. And if that's done right, then this whole problem goes away without having to make sure that every project you work on is configured correctly to avoid pulling in the unit tests from everything that it depends on.

And maybe figuring out what to do about __traits(getUnittests) complicates things, but it seems like the fact that we're even having this problem is due to a flaw in the design of D's unit tests and that that should be fixed, not worked around.

- Jonathan M Davis

« First   ‹ Prev
1 2 3 4 5 6