Script loading performance tests
Attempts to determine and compare load times between dynamic script loading strategies:
script.src = url
script.src = dataURI
script.text = code
(added 1 Aug 2013)Function(code)
(added 2 Aug 2013)
Test page
Test page loads jquery files first, then loads codebase.js.
Buttons let you re-load the codebase.js using the various strategies.
Results
Results indicate total time in milliseconds for each type of strategy (clean, get, run, end), plus average times.
[ 1 AUG 2013 ]
Originally this test covered only the src attribute, comparing URL vs dataURI performance, the URL pointing to a static CDN domain. In that setup, URL generally outperformed the dataURI across browsers - except for Internet Explorer (8-10) which processed the dataURI even faster than Chrome.
After adding the script.text
strategy, the scripts needed to be modified so that all create > exec >
profile sequences were fair. That meant moving the remote script to this repo and wrapping the entire
script body in a function that could be called externally by any of the three strategies. This gives
more control over the source, and, apparently, prevents script caching in the browser, due to the
proxying done by rawgithub.
Results of the 3 scripted dom element strategies now mimic an empty cache (so it's first-hit comparison only).
The script.text = code
strategy wins for all but IE where text vs URL are within 20ms (ymmv).
The script.src = url
strategy performs worst - except in IE again - but previously, when hitting
the static CDN, script.src
performed best - except in IE).
The script.src = dataURI
strategy performed a bit faster than script.src = url
-
except that it was quite crash prone in Chrome and Firefox, and often performed orders of magnitude worse in
Firefox on the first hit.
[ 2 AUG 2013 ]
Added Function(code)
strategy to compare performance vs. scripting dom elements.
[ 15 AUG 2013 ]
Added averages in display.
Chrome 28 | Firefox 22 | Opera 12 | IE 10 | |
---|---|---|---|---|
src URL | 600ms | 600ms | 520ms | 200ms (amazing) |
dataURI | 100ms (crash prone) | 125ms (crash prone) | 185ms | 250ms |
script.text | 40ms | 80ms | 44ms | 185ms |
Function(code) | 25ms (100ms first time) | 28ms | 26ms | 25ms |
Discussion
The point of all this had been to ferret out performance gains in time-to-first-byte and time-to-load.
[2 AUG 2013 ] - However, the Function(code)
strategy appears to have best performance
across the board, barely ahead of script.text = code
. In Chrome, the first invocation
of Function(code)
always took 100+ ms. Tobie Langel was right. Lazy evaluation reduces
startup latency: Lazy evaluation of CommonJS modules
Using dataURI
means the script string is larger than the original source.
Using script.text
and Function(code)
means you have to transform or encode
or stringify the actual script source file.
Using script.src
means you don't have to stringify the script file but you're then subject to
request latency over the network.
Both script.text
and dataURI
mean more bytes in the initial page load if they're inlined.
But if they reside as vars or map entries in a src-referenced script, then the initial html payload isn't so bloated.
[ 24 JUL 2013 ] - dataURI performance and power consumption on mobile poorer than URL fetch - see data-uris are slow on mobile
[1 AUG 2013 ]
Setting window.codebase = null;
in the removeScript() function revealed that script should be
attached to the DOM before script.text = code
assignment ~ order matters!
Next Up
[ 31 JUL 2013] - explore browsers' built-in lookahead + prefetch capabilities effectively to load additional scripts as strings, such as in a build map file with each script url containing the stringified version of the source (this will probably be in its own repo).