Issue 14431 - [REG 2.067.0] huge slowdown of compilation speed
Summary: [REG 2.067.0] huge slowdown of compilation speed
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 regression
Assignee: No Owner
URL:
Keywords: performance, pull
: 14540 (view as issue list)
Depends on:
Blocks:
 
Reported: 2015-04-10 01:59 UTC by Martin Nowak
Modified: 2015-09-02 04:10 UTC (History)
7 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Martin Nowak 2015-04-10 01:59:22 UTC
People are reporting ~25% slowdown in compilation speed when upgrading from 2.066.1 to 2.067.0.

http://forum.dlang.org/thread/pettuhnkkhwwgnqucrua@forum.dlang.org#post-pettuhnkkhwwgnqucrua:40forum.dlang.org
Comment 1 Daniel Kozak 2015-04-10 09:22:03 UTC
My timings:
 	           2.066.1|  2.067
-----------------------------------------
debug -c	   4.300  |  4.500
debug -c -o-	   3.500  |  3.500
release -c	   4.000  |  4.100
release -c -o-	   3.260  |  3.310
release -c -O	   6.400  |  6.700
release -c -o- -O  3.280  |  3.320
release	           5.750  |  5.600
release -O	   8.200  |  8.100


So for me difference in compile speed is almost same
Comment 2 Daniel Kozak 2015-04-10 09:24:52 UTC
s/same/none
Comment 3 Wyatt 2015-04-10 17:03:38 UTC
(In reply to Daniel Kozak from comment #1)
> 
> So for me difference in compile speed is almost same

I wonder if this isn't at least partially platform-dependent?
Comment 4 Martin Krejcirik 2015-04-13 14:06:02 UTC
I'm not sure how relevant this is to the general compilation speed, but anyway:

import  std.regex;

auto RE_VARSET = regex(r"(?<!!\w+.*)!(\w+)\s*=\s*([\w!.-]+|`.+`|" ~ `".*")[ \t]*`,"i");
auto RE_CMD    = regex(r"!([A-Z_]+)\(([A-Za-z0-9_ .:;!,@{}/*-]*)\)");


dmd 2.065
real    0m3.789s
user    0m3.548s
sys     0m0.232s

dmd 2.066.1
real    0m4.628s
user    0m4.328s
sys     0m0.292s

dmd 2.067
real    0m5.260s
user    0m4.940s
sys     0m0.308s
Comment 5 Martin Nowak 2015-04-20 04:39:46 UTC
(In reply to Martin Krejcirik from comment #4)
> I'm not sure how relevant this is to the general compilation speed, but
> anyway:
> 
> import  std.regex;
> 
> auto RE_VARSET = regex(r"(?<!!\w+.*)!(\w+)\s*=\s*([\w!.-]+|`.+`|" ~ `".*")[
> \t]*`,"i");
> auto RE_CMD    = regex(r"!([A-Z_]+)\(([A-Za-z0-9_ .:;!,@{}/*-]*)\)");

This spends most of it's time in CTFE interpretation.
I get a 5-10% speedup when compiling v2.067.0 on my machine vs. using the released binary, most likely because of a newer gcc 4.9.2 vs. gcc 4.7.2 on the debian build image.
Comment 6 Martin Nowak 2015-04-20 05:15:00 UTC
That orange library is a really terrible example. Why would someone use single file compilation for object and header only to pack everything into a static library.
If I do build everything at once (including headergen -Hfimport -op) this takes 400ms instead of 8.5s.
There is still a slowdown from 400ms to 450ms comparing 2.066.1 and 2.067.0.
Seems to be mostly cause by more allocations in the compiler.
Comment 7 Martin Nowak 2015-04-20 05:38:44 UTC
This slowdown comes from https://github.com/D-Programming-Language/dmd/pull/4384, which does instantiate additional templates in order to resolve link bugs.
The problem is amplified by using single file compilation.
Comment 8 Iain Buclaw 2015-04-20 15:44:57 UTC
(In reply to Martin Nowak from comment #5)
> (In reply to Martin Krejcirik from comment #4)
> > I'm not sure how relevant this is to the general compilation speed, but
> > anyway:
> > 
> > import  std.regex;
> > 
> > auto RE_VARSET = regex(r"(?<!!\w+.*)!(\w+)\s*=\s*([\w!.-]+|`.+`|" ~ `".*")[
> > \t]*`,"i");
> > auto RE_CMD    = regex(r"!([A-Z_]+)\(([A-Za-z0-9_ .:;!,@{}/*-]*)\)");
> 
> This spends most of it's time in CTFE interpretation.
> I get a 5-10% speedup when compiling v2.067.0 on my machine vs. using the
> released binary, most likely because of a newer gcc 4.9.2 vs. gcc 4.7.2 on
> the debian build image.

Maybe the speculative devirtualization in gcc-4.9 is in some part responsible for that.  Just thinking out loud...
Comment 9 Martin Nowak 2015-04-20 22:09:21 UTC
(In reply to Iain Buclaw from comment #8)
> Maybe the speculative devirtualization in gcc-4.9 is in some part
> responsible for that.  Just thinking out loud...

We should probably update the compilers across the bank to build releases.
Especially replacing DMC with VS would result in a huge speedup.
Comment 10 Martin Nowak 2015-05-08 00:59:06 UTC
*** Issue 14540 has been marked as a duplicate of this issue. ***
Comment 11 weaselcat 2015-05-22 23:54:46 UTC
Hi,

maybe it's best to promote CyberShadow's "Are we slim yet?" histogram tool? It was able to easily pinpoint exactly which commit caused this.

http://digger.k3.1azy.net/trend/

maybe some sort of automated regression alert.
Bye.
Comment 12 Walter Bright 2015-06-27 20:57:50 UTC
(In reply to Martin Nowak from comment #7)
> This slowdown comes from
> https://github.com/D-Programming-Language/dmd/pull/4384, which does
> instantiate additional templates in order to resolve link bugs.
> The problem is amplified by using single file compilation.

The trouble is the compiler would not instantiate a template if that template was already instantiated by an imported model, on the assumption that the instantiation would exist in the object code generated when the imported module was separately compiled.

The problem was that if A imports B, and B imports A, A and B are compiled separately, and so the template was never instantiated (see https://issues.dlang.org/show_bug.cgi?id=2644). The 4384 fixed this by always instantiating templates if the imported module also imported root modules, as computed by TemplateInstance::needsCodegen().

The trouble with that, and the slowdown, is the commonplace practice of having every module in a project import every other module.

An obvious workaround for users is to compile modules that mutually import each other on the same command to dmd.

A possible solution to this was proposed by Martin Nowak:

"I think we should define a rule for which module is responsible for the instantiation when they mutually import each other. I'd suggest that the module with the lexicographically smaller module name does it."
Comment 14 github-bugzilla 2015-08-30 19:18:35 UTC
Commits pushed to stable at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/6c14fadca403a61a578795ec0fb71f9340c7b543
fix Issue 14431 - huge slowdown of compilation speed

In the pull request #4384, all instance has been changed to invoke
semantic3(). It was for the link-failure issue in specific case, but it
was too excessive.

1. Semantic analysis strategy for template instances:
  We cannot determine which instance does not need to be placed in object
file until semantic analysis completed. Therefore, for all templates
instantiated in root module, compiler should invoke their semantic3 --
regardless of whether those are also instantiated in non-root module. If
a template is _only_ instantiated in non-root module, we can elide its
semantic3 (and for the compilation speed we should do that).

2. Code generation strategy for template instances:
  If a template is instantiated in non-root module, compiler usually does
not have to put it in object file. But if a template is instantiated in
both of root and non-root modules which mutually import each other, it
needs to placed in objfile.

https://github.com/D-Programming-Language/dmd/commit/92fcc9da72e2889406031a34d9a5d22b075f7d50
Merge pull request #4944 from 9rnsr/fix14431

[REG 2.067.0] Issue 14431 - huge slowdown of compilation speed