Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Startup performances #53

Open
loicrouchon opened this issue Nov 26, 2013 · 24 comments
Open

Startup performances #53

loicrouchon opened this issue Nov 26, 2013 · 24 comments
Assignees
Labels
Milestone

Comments

@loicrouchon
Copy link
Member

I've noticed that it takes quite some time to startup a ceylon program.

I made the following tests:

Simple hello world program in both java and ceylon

Java version:

public class Hello {
  public static void main(String[] args) {
    System.out.println("hello");
  }
}

compiled with javac Hello.java and run with time java Hello
In average:

real    0m0.060s
user   0m0.050s
sys    0m0.012s

ceylon version:

shared void run(){
  print("hello");
}

compiled with ceylon compile hello and run with time ceylon run hello
In average:

real    0m1.445s
user   0m1.050s
sys    0m0.074s

Ceylon: lastest version from git
Java: openjdk "1.7.0_25"
OS: Ubuntu 13.10 64bits

I don't know if it's those differences are because of JBoss modules initialization, ceylon.language classloading or because of some specific ceylon startup process I'm not aware of.

I'm not really concerned about the fact that it's slower than java, but I would like to know if this can be improved to something more acceptable for command line tools like ceylon.build (below 200ms would be a great start)

@tombentley
Copy link
Member

The tool stuff is another possible culprit

@alesj
Copy link
Member

alesj commented Nov 26, 2013

@FroMage
Copy link
Member

FroMage commented May 5, 2014

So half of that time is spent trying to find the module version. If you run with ceylon run hello/1 you will see it takes about 800ms instead of 1500ms.

@FroMage FroMage modified the milestones: 1.0, 1.1 May 5, 2014
@FroMage FroMage self-assigned this May 5, 2014
@FroMage
Copy link
Member

FroMage commented May 5, 2014

The biggest offenders:

  • CeylonTool.getTool: 120ms
  • checkModuleVersionsOrShowSuggestions: 600ms
  • starting JBoss modules: 180ms
  • creating JBoss modules class loader: 141ms
  • Metamodel init: 91ms
  • running the Ceylon code: 200ms

Total of the biggest offenders: 1332ms

@FroMage
Copy link
Member

FroMage commented May 5, 2014

checkModuleVersionsOrShowSuggestions appears to be 200ms when --offline, so the online part is only 400ms

@quintesse
Copy link
Member

Yes, the looking up of possible versions comes at a cost, and I agree that it seems pretty high. Most of that probably comes from somewhere deep down in the CMR. For what it does (in most cases just seeing if certain files exists in a certain directories) it seems a bit much.

@quintesse
Copy link
Member

Btw, one thing I had been thinking about to prevent the online cost on each invocation is to only query the online repositories if zero or multiple versions were found locally (cached or otherwise). Of course that would make the failure case (no versions exist neither locally nor online) even slower.
(edited for correctness: multiple versions also trigger this situation)

@FroMage
Copy link
Member

FroMage commented May 5, 2014

Yeah, so I'm improving it so that it will use whatever version is already compiled in the current output folder if there's only one, or whatever version is present in source. That's a lot faster.

FroMage added a commit to ceylon/ceylon-compiler that referenced this issue May 6, 2014
…e module file we need

and for default module, do not visit modules and stop at the first source file found
FroMage added a commit to ceylon/ceylon-common that referenced this issue May 6, 2014
FroMage added a commit to ceylon/ceylon-common that referenced this issue May 6, 2014
FroMage added a commit to ceylon/ceylon-module-resolver that referenced this issue May 6, 2014
…iled output, then in source

If found, we do not check for other versions as this is the most likely candidate, and the fastest too
@FroMage
Copy link
Member

FroMage commented May 6, 2014

Actually running it is just 10ms, my bad.

@FroMage
Copy link
Member

FroMage commented May 6, 2014

I've made several improvements and now finding a compiled module or a source module is a lot faster. There's still improvement to be done in CeylonTool.getTool (sure we can bring this down from 120ms), let's see if I can find something obvious.

@FroMage
Copy link
Member

FroMage commented May 6, 2014

Note that for some reason, parsing a single module file takes 150ms. I guess from initialisation of AntLR?

@FroMage
Copy link
Member

FroMage commented May 6, 2014

Added related ceylon/ceylon-compiler#1631 for compiler speed for trivial modules.

@tombentley
Copy link
Member

CeylonTool.getTool indirectly ends up doing a lot of reflection in order to instantiate the tool and inject it according to the arguments given on the command line It has to build a whole model of the tool to do this. That's pretty inefficient given that the model won't be reused and all this is standing in the way of actually running the program.

One thing which would speed it up a lot was if, for each tool, we generated a class (using an annotation processor) which did the parsing for that tool. That way the main tool would only need to instantiate the relevant class and give it the command line arguments, and all the reflection would be avoided. But that's a lot of work.

It has been noted that our tooling is a lot like JBoss forge, and I would have suggested that in the long term we look to use that. But then it turns out that their performance isn't great either

@FroMage
Copy link
Member

FroMage commented May 6, 2014

Do you think alternative reflection libs would help?

@tombentley
Copy link
Member

No idea. What, specifically, did you have in mind?

@FroMage
Copy link
Member

FroMage commented May 6, 2014

Nothing, just wondering if something like Scannotation would be faster.

@FroMage
Copy link
Member

FroMage commented May 6, 2014

Hah, it looks like the main issue is that we create lots of models instead of just one ;)

@tombentley
Copy link
Member

I don't think Scannotation would help because fundamentally something has to instantiate the tool and call a bunch of setters. AFAICS, Scannotation cannot make invoking those setters any faster. Maybe using method handles would help. But avoiding any kind of reflection would be fastest.

@FroMage
Copy link
Member

FroMage commented May 6, 2014

[0ms] getToolModel for ''
[37ms] getToolModel done
[41ms] getToolModel for 'run'
[154ms] getToolModel done
[154ms] getTool bind for 'run'
[163ms] getTool bind done
[164ms] getToolModel for 'run'
[175ms] getToolModel done
[175ms] getTool bind for 'run'
[176ms] getTool bind done
[177ms] getToolModel for 'run'
[185ms] getToolModel done
[185ms] getTool bind for 'run'
[187ms] getTool bind done

@tombentley
Copy link
Member

Mmm, well that looks stupid.

@FroMage
Copy link
Member

FroMage commented May 6, 2014

So once I removed a few too many instantiations of Tool, I am down to finding that iterating /usr/bin to detect path plugins takes about 100ms. I cut it down to 40ms using NIO2 and changing the order of the file tests.

@tombentley
Copy link
Member

Out of interest what's the cost of CeylonTool.getTool() now?

FroMage added a commit to ceylon/ceylon-common that referenced this issue May 6, 2014
FroMage added a commit to ceylon/ceylon-common that referenced this issue May 6, 2014
FroMage added a commit to ceylon/ceylon-common that referenced this issue May 6, 2014
@FroMage
Copy link
Member

FroMage commented May 6, 2014

So now, a Hello World runs in 800ms. I'm going to stop optimisation for 1.1, and move this issue to 1.2 when we have more time.

@FroMage FroMage modified the milestones: 1.2, 1.1 May 6, 2014
@FroMage
Copy link
Member

FroMage commented May 6, 2014

The whole tool setup seems to be around 140ms now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants