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

Add force compilation flag to serve #128

Closed
wants to merge 2 commits into from
Closed

Add force compilation flag to serve #128

wants to merge 2 commits into from

Conversation

rikhuijzer
Copy link
Contributor

@rikhuijzer rikhuijzer commented Oct 1, 2021

@tlienart this implements the thing I was talking about on Slack. See also JuliaWeb/HTTP.jl#720 for a previous discussion.

Give this PR a very critical review please. For me, this would be a great addition making me life a bit better. However, I'm also aware that it is quite a hacky solution. For example, it wouldn't help people who have "open link in browser" on by default (unless their browser is very slow, then this PR would speed things up a bit).

Also, notice that this is sort of breaking since it defaults to yes. I don't think that it would break any user configuration, but maybe it requires a breaking release.

@rikhuijzer rikhuijzer changed the title Add trigger compilation flag to serve Add force compilation flag to serve Oct 1, 2021
@tlienart
Copy link
Collaborator

tlienart commented Oct 1, 2021

Hey Rik, thanks for this; I will test this a bit to make sure it doesn't affect the current user experience but before that I have a few questions:

can you explain in more details (assume I'm very very dumb which is not far from the truth) why this would be helpful? I'm not sure I understand what is going on. E.g. this can speed up the time between calling serve` and seeing the webpage.

Could you maybe present a situation where this would be "felt"? I just tried this in the generated directory of the julialang website and julia -e "using LiveServer; serve(launch_browser=true)" takes maybe half a second until a tab in my browser is opened with the site displaying. And I think most of that time is the browser opening the tab. This can be cut further on the Julia process side by not closing that tab; just doing serve() and refreshing the tab manually once. Or just opening the address manually after having done serve().

Are you suggesting we cut that time further? or just that we don't wait for the browser to finish loading the tab before doing something else?

I apologise if this is all dumb but I want to be super sure of what's going on.

Also, what does the 0.3s delay do?

Thanks!

@rikhuijzer
Copy link
Contributor Author

rikhuijzer commented Oct 1, 2021

Could you maybe present a situation where this would be "felt"? I just tried this in the generated directory of the julialang website and julia -e "using LiveServer; serve(launch_browser=true)" takes maybe half a second until a tab in my browser is opened with the site displaying.

May I ask what CPU you have? Here, it is way more than half a second. If I do this in one terminal:

(master) $ cd LiveServer.jl/

(master) $ julia --project

julia> using LiveServer: serve

julia> serve()
✓ LiveServer listening on http://localhost:8000/ ...
  (use CTRL+C to shut down)

Then, I can go into another and get:

(master) $ cd LiveServer.jl/

(master) $ julia --project

julia> using HTTP: get

julia> @time get("http://google.com"); # Compiles HTTP.get.
 3.928030 seconds (7.05 M allocations: 404.515 MiB, 6.05% gc time, 1.25% compilation time)

julia> @time get("http://google.com"); 
  0.130081 seconds (21.22 k allocations: 1.399 MiB, 20.39% compilation time)

julia> @time get("http://localhost:8000/"; status_exception=false); # Triggers LiveServer.serve compilation.
  3.407043 seconds (250 allocations: 204.297 KiB)

julia> @time get("http://localhost:8000"; status_exception=false);
  0.001260 seconds (240 allocations: 204.125 KiB)

And these three seconds are what I hope to reduce. It's very annoying to go into the browser after having restarted the process for whatever reason (updated deps changed structs probably), refreshing the page and having to wait these seconds.

But, I also understand that this is sort of a first-world problem.

Also, what does the 0.3s delay do?

I thought it makes sense to give the async process some time to connect to the socket. HTTP.retry probably makes more sense.

@tlienart
Copy link
Collaborator

tlienart commented Oct 1, 2021

Ah ok so specifically in your use case you require this get("http://localhost:8000/"; status_exception=false); to not be super slow the first time?

What's the workflow for Books that you want? (i.e. why do you want to get the page?)

(sorry for all the questions, I'm just trying to be fully clear on what this solves 😂 + whether it's justified to make it a default as opposed to a specific path that could be toggled when Books calls it i.e. have your keyword false by default and true for specific users?)

@rikhuijzer
Copy link
Contributor Author

Yeah no worries. You are asking valid questions.

What's the workflow for Books that you want?

The Books workflow is basically the same as Franklin. The user calls serve and jumps into the browser. In my case, I don't always use open_browser=true because I already have a tab open from before. I just run julia --process -ie 'using Books; serve() and do some other stuff while Books, LiveServer and HTTP compile. The example uses HTTP.get because it gives nice information about the running time. Also, it uses status_exception=false only because @time HTTP.get returns a 404 in the LiveServer.jl directory. Normally, I never use status_exception=false.

I could just as well implement this very easily in Books.jl, but thought other people could benefit from it too (Franklin and other packages). My idea is to just have this as a hidden thing in LiveServer.jl which isn't noticeable, but speeds things up in the background.

toggled when Books calls it i.e. have your keyword false by default and true for specific users?

My fear of setting it to false by default is that no one would use it. Typing serve(force_compilation=true) also takes about 3 seconds so there isn't much speed gain.

takes maybe half a second until a tab in my browser is opened with the site displaying.

I really should get a CPU with better single threaded performance. Yours seems to be 3-6 times as fast.

@tlienart
Copy link
Collaborator

tlienart commented Oct 1, 2021

Hmm ok I understand the bit about running time information. And the rest are fair points.

At the risk of committing sacrilege, I wonder whether similar runtime information could be obtained via some javascript lib or some shell stuff; HTTP.jl is just a bit of a mess though now that Jacob is looking after it things might get quite a bit better.

Anyway I think the change you're suggesting is not crazy, I just want to test it heavily before "baking it in", assuming it 'just works' all the time, I'm happy to change things, and we can always get back to it if you find a better way of doing this.

PS1: do you think "warming up" get via a precompilation statement (the kind of tricks generated by SnoopCompile) could help with this first get being faster?

PS2: I'm using a fairly beefy work laptop with an i7 processor but I have another slower and older i5 lying around on which I'll do the tests

@rikhuijzer
Copy link
Contributor Author

At the risk of committing sacrilege, I wonder whether similar runtime information could be obtained via some javascript lib or some shell stuff; HTTP.jl is just a bit of a mess though now that Jacob is looking after it things might get quite a bit better.

Good point. curl would have been clearer for the time information because I wouldn't have to be so careful about warming up caches.

PS1: do you think "warming up" get via a precompilation statement (the kind of tricks generated by SnoopCompile) could help with this first get being faster?

Not so much. It went from 3.2 seconds to 2.7 seconds JuliaWeb/HTTP.jl#750.

Thanks for the CPU info.

@rikhuijzer
Copy link
Contributor Author

Anyway I think the change you're suggesting is not crazy, I just want to test it heavily before "baking it in", assuming it 'just works' all the time, I'm happy to change things, and we can always get back to it if you find a better way of doing this.

Okay. Makes sense. Feel free to "finish" the PR or close it if you decide to do so after your testing.

PS1: do you think "warming up" get via a precompilation statement (the kind of tricks generated by SnoopCompile) could help with this first get being faster?

The problem with precompilation, as far as I understand, is that it doesn't compile upstream packages. In this case, the culprit is mostly HTTP, so precompiling LiveServer.jl wouldn't help too much. See JuliaLang/julia#42016 for more information.

@rikhuijzer
Copy link
Contributor Author

For me, this would be a great addition making me life a bit better.

I'm gonna go for PackageCompiler.jl. It's a bit of a hassle to manage the right sysimage for each project, but it is much quicker once set up.

@rikhuijzer rikhuijzer closed this Oct 21, 2021
@tlienart
Copy link
Collaborator

Ah sorry @rikhuijzer for not taking this on, I forgot about it 😕 . Good if you have an alternative that works fine! I've never really managed to successfully use PackageCompiler.jl but maybe should give it another shot.

@rikhuijzer
Copy link
Contributor Author

Ah sorry @rikhuijzer for not taking this on, I forgot about it confused

No worries. It's not really important :)

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

Successfully merging this pull request may close these issues.

2 participants