Load performance
Overview
Since CPO is used as part of class assignments, sometimes via cheap Chromebooks on overloaded wifi networks, I wanted to check on the experience of trying to load it quickly in a challenging environment.
I'm curious:
- Have teachers and students ever complained about the load time of CPO?
- Who has access to the logging data for load time? (It's sent as the
pagevisevent toLOG_URL)
Research
I evaluated CPO with CPU throttling set to 1/6 of my fast computer and my internet throttled to 1Mbps, 40ms RTT delay.
| Situation | First paint | Usable | Notes |
|---|---|---|---|
| Cold cache | 4s | 45s | Several long periods where animations froze |
| Warm cache | 2s | 14s | " |
Poking at DevTools, a few things stand out:
- In the cold cache case, downloading cpo-main.jarr is the vast majority of the time. The file is hosted by a CDN but just quite large.
- In both cases, there are a lot of parallel requests for small JS files from our domain that could be faster if bundled together.
- In the warm cache case, we are still requesting all files again. A total of 1.5s wall clock time is used just to get a bunch of 304s and load them from cache.
- localSettings.js is loaded in the
<head>and blocks later parsing, rendering, and network requests. - There are some dependencies that aren't clearly needed at all and some that are used only just a tiny bit.
- dexie (53kb) is loaded from npm but is only used in the
IndexedDBBackendlogger, which appears to be unused. - jQuery UI (250kb) is only loaded for the resize handle between the editor and REPL
- dexie (53kb) is loaded from npm but is only used in the
Suggestions
- The biggest, but hardest, improvement would be to slim down the size of the
cpo-main.jarrover in brownplt/pyret-lang. There appears to be a lot of info left over from the bootstrap process that isn't really needed in CPO. (For example, a ton of the file is just source locations and metadata for expressions in the Pyret source for the compiler. That's useful if you're debugging the compiler itself, but probably not needed for students using CPO.) - [ ] Use requirejs to bundle all the files loaded locally in editor.html into a single file (saves lots of parallel network requests) and put a version in that file name so we can use it from local cache without checking with the server.
- [ ] Rearrange
localSettings.jsand the inline js in editor.html to be loaded at the bottom via the requirejs bundle.
Feedback wanted
There are some largish suggestions here and I don't want to impose something that will have to be maintained forever that is too complex to understand. It may also be worth deferring this kind of work and adopting performance improvements as part of the React version that folks are working on.
-
Thanks for bringing this up. My simple bundling/minifying efforts typically stalled when cpo-main would e.g. crash acorn and esprima (and since that's such a large chunk of code, why bother with the rest, my fatalistic past self would say).
It's a really astute observation that changing the compilation of the compiler to cut out unnecessary information is worth exploring here. I think that is probably the biggest opportunity for improvement, and would involve hacking the compiler a bit. That's probably worth doing at some point, and I think it probably could be flagged/optioned in a relatively maintainable way. There's a bunch of places where unnecessary information is around, and we could also strip out lots of the type annotations as well in the compiled compiler. That's probably a long, useful conversation to start.
-
If there's a straightfoward bundling solution for the other stuff, that's a good idea. The index page already uses webpack bundling to put itself together, so there's no massive new dependency in applying that to the editor page.
-
Happy to take a load-order PR that just moves around script tags in document order –thanks for noticing that.
Spoke with Joe about this today.
Given the enormous improvements @asolove landed along these lines with PRs that year (and the bundling improvements to come thanks to anchor+webpack), I'm going to close this issue. The one item that has _not _ been addressed is compiling the compiler down to something slimmer. This may be worthwhile to think about in the future, but there's no urgent need right now. If folks disagree with me closing on these grounds, I'd propose opening a separate issue that's focused on that one task