Fabrice Bellard's PC emulator implemented in Javascript is impressively fast--it boots a small Linux image in the browser within a few seconds.
What techniques were used to get this performance?
Fabrice Bellard's PC emulator implemented in Javascript is impressively fast--it boots a small Linux image in the browser within a few seconds.
What techniques were used to get this performance?
Share Improve this question asked Jun 5, 2011 at 19:08 nibotnibot 15k8 gold badges58 silver badges61 bronze badges 5- 1 One reason are typed arrays I guess, as written here: The code is written in pure Javascript using the W3C Typed Arrays. A slightly slower fallback mode is implemented for browsers missing this support. – Felix Kling Commented Jun 5, 2011 at 19:22
- @Felix Kling - It boots linux (and piles the example program) quite fast even in IE9, which I don't think has typed arrays (not sure about that). – Daniel Earwicker Commented Jun 5, 2011 at 19:27
- @Daniel: I'm not saying that this is the only reason ;) I don't know about IE9... – Felix Kling Commented Jun 5, 2011 at 19:29
- Yeah, I'm just raving about how cool it is! I used to explain to people how generally powerful JS is by saying "You could write a VM in it, in principle - it could run Linux, or whatever! Obviously in practice it would be ridiculously slow..." But I've owned real PCs that boot linux slower that this. So I need a new example. I and some colleagues were just laughing in astonishment at it when we first saw it. I assumed it was a cheap hoax until I'd dug into it a bit. – Daniel Earwicker Commented Jun 5, 2011 at 19:33
- Woops, this is a dupe of stackoverflow./questions/6030407/… – nibot Commented Jun 6, 2011 at 13:00
4 Answers
Reset to default 5I believe that sharing some general credit with "speed" of the modern JS interpreter is a far way an offtopic in the list of Bellard's techniques (since he does not replace browser's engine). What are his optimization techniques? is a great question and I would like to get a more detailed record on it.
The points I can name so far
- (Optional) JS Typed arrays exclude unnecessary memory allocation dynamics (resizing). Fixed type (size) allows to allocate contiguous blocks of memory (with no variable-length elements' segments in such blocks) and uniformly address elements of a single type.
- Fast boot by a custom minimalistic booter (see linuxstart code published by Fabrice, also see his project called TCCBOOT http://bellard/tcc/tccboot.html)
- Optimized unpressed embedded kernel (See the kernel configuration, it is extra tiny and optimized for small "linuxes").
- Minimal number of devices (Devices are super standard and easy to recognize by the kernel. So far, I have properly studied serial device but the rest benefits from similar properties). Ramdisk initialization is rather slow though.
- Small (2048 blocks) unpressed root.bin ext2 system. The root system consists of minimal bination (rootfs, proc, tmpfs, devpts). No swap.
- (Unsure) he has patched the buffer size for ttyS0 (serial port device, or actually the kernel UART driver - to be precise) which municates to terminal. Communication is in any way buffered using his term.js binding (I have found no transmit buffer in UART itself). Note that emulation (as in this case) can be much faster than the real thing.
Please also mind the browser cache while refreshing the page. It kicks very fast if its all in memory (optimized by the host OS). Performing direct (if cached - in-memory) copying (with load_binary()) of "unpressed" binary segments (start_linux.bin, vmlinux26.bin, root.bin). No hard disk I/O limitations.
I used the excellent http://jsbeautifier/ to prettify the minified JS code. It looks to me like painstakingly written, un-fussy, sensible procedural code. It's a magnificent achievement in itself, but the credit has to be shared with the phenomenal performance of modern JavaScript interpreters.
As of 2018, Fabrice has used asm.js and WebAssembly to achieve this.
You can read more here.
If you look at the Inspector (or we know as Chrome DevTools, or Firefox's Inspector), you would see some wasm://
sources (on Firefox), implying that he used WebAssembly to achieve this.
Maybe using a C to JavaScript piler? Like Emscripten: http://code.google./p/emscripten/