30 ms·
Microvium Is Small
- jpgvm 4y agoImpressively small and trade-offs seem pretty reasonable. (namely lack of runtime parser, minimal built-ins). Initially thought the lack of built-ins would be annoying but it looks very easy to simply "re-implement" them given how easy the C-interop is to use. JS isn't my favourite but with such a small VM implementing what is a fundamentally a very modern scripting language I would be tempted to use it on my next embedded project. The other seemly killer feature from my perspective is ability to snapshot the VM state to stable storage and resume on reboot rather than start from new execution context.
- bsder 4y ago> Impressively small and trade-offs seem pretty reasonable. (namely lack of runtime parser, minimal built-ins). Not really. If you remove the runtime parser, then you're effectively just a VM and there are lots of VMs significantly smaller than this. Anytime you attempt to implement a language in a tiny amount of memory, a ridiculous chunk of it goes to implementing the parsing system. Infix parsing is particularly expensive to implement--which is why the only two languages in the extremely tiny space are Forth and Lisp.
- jpgvm 4y agoFair, I should have qualified my statement to "for JS". I don't think it's reasonable to compare to Forth/Lisp (or even Lua despite similar language capabilities) because of how pervasive JS is from a runtime perspective. Especially because this implements a sufficiently good subset that you can run isomorphic code on device, backend, browser.
- taylorbuley 4y agoThere's some irony in the rhetorical length to which this brilliant coder goes in order to justify the benefits of its byte-sized brevity.
- booi 4y agoThis audience is probably a little more used to measuring things like ram in gigabytes and storage in tera/petabytes. It’s nice to be reminded that not all our devices are like that but high level languages are still possible
- dmitrygr 4y ago> Microvium on the other hand uses malloc and free to allocate when needed and free when not needed on micros which lack an MMU (all of the ones allegedly targeted), this is how you fragment your memory to hell and eventually cause hard-to-debug crashes
- sitkack 4y agoMaybe it has support for typed arrays. Even for high level languages, usually on a micro, the main loop doesn't use any memory, or at least doesn't allocate. Not splaining u, I am familiar with your work.
- dmitrygr 4y agoThe Malloc/free thing is weirder and weirder the more I think about it. Js is a managed language. Instead of pointers you can use handles (double printers, via an indirection Table) and with a custom allocator you could compact the heap and thus avoid fragmentation. (This is what I remember doing in my tiny Java vm a decade ago). Malloc/free actively preclude this and force the fragmentation on you.
- codermike 4y agoMicrovium does use a compacting heap, something similar to a semi-space collector except that it can free up the unused "space". Have a look for some of the details: https://coder-mike.com/blog/2020/07/08/new-garbage-collector/ https://coder-mike.com/blog/2020/07/08/new-garbage-collector... But the malloc/free thing referenced in the article is mainly about the stack space and core registers, which would just be wasting space if the VM was idle.
- AHTERIX5000 4y agoSo what's the allocation pattern like (regarding malloc/free)? Last time I used scripting language in constrained environments it was Duktape and one of the issues was wildly varying allocations ranging from few bytes to kilobytes depending on usage. We ended up implementing TLSF like allocator which worked well in the end.
- dvt 4y agoCalling Microvium an "engine" without a runtime parser is a bit inaccurate imo. The entire purpose of Javascript is that it's a "scripting" language, so having an interactive runtime is kind of the point. And as @dmitrygr already pointed out, not using malloc/free is actually a feature, not a bug[1]. [1] https://johnysswlab.com/the-price-of-dynamic-memory-allocation/ https://johnysswlab.com/the-price-of-dynamic-memory-allocati...
- ricardobeat 4y agoThe main concern seems to be memory usage. Dynamic allocation reduces the memory footprint, the author compares it to the best alternative which requires pre-allocation of a large chunk of memory. You’d be compiling the majority of other options too for embedded, so that’s not really a drawback.
- dvt 4y ago> Dynamic allocation reduces the memory footprint, the author compares it to the best alternative which requires pre-allocation of a large chunk of memory. Architecturally speaking, it makes almost no sense to have dynamic memory allocation in Microvium. You could theoretically even do static analysis on whatever chunk of code you're about to run and figure out exactly what your upper bound for memory usage would be. (Remember, we don't have an interactive runtime.) So now that I actually think about it more, not pre-allocating in this particular case is actually an antipattern.
- ricardobeat 4y agoThe author has a different perspective on that. From the article: > In typical firmware, idle memory is much more important than peak memory, as I explained in my last post. https://coder-mike.com/blog/2022/05/27/single-threading-is-more-memory-efficient/ https://coder-mike.com/blog/2022/05/27/single-threading-is-m...
- codermike 4y agoThe static analysis in Microvium does do this for the stack variables, but the heap is not bounded. It's trivial to write a for-loop or something that creates N new objects.
- gigel82 4y agoHow about an (actually small but ES6 feature complete) JS engine for general computers? QuickJS showed so much promise (especially given the pedigree) but it's been dead for a year and it never really delivered on the promise of being small (I guess the code is small, but at runtime it takes more memory than engines with full JIT like V8 or Chakra). Hermes looked interesting, but it's clear it will never be an actual JavaScript engine, it's more like a React Native engine that interprets some subset of JavaScript. Duktape struggles with larger bundles and especially with deep call stacks (same as QuickJS) and the C API gives me strong Lua vibes (which may be a positive for some).
- ricardobeat 4y agoThe last commit on QuickJS is from March. Do you have a source for that memory use comparison with V8? I haven’t had first-hand experience with it. I do have experience using Duktape and haven’t had any issues with large call stacks, but also haven’t tried to run anything like a React app in it. The C API was indeed very enjoyable to use.
- deleted 4y ago[deleted]
- juancampa 4y ago> never really delivered on the promise of being small I wonder why you say this. I just ran both qjs and node's REPL and qjs is taking 2.4MB vs 21.5MB for node. Are you referring as QuickJS running with a specific workload? Do you happen to have more info on this measurement?
- juancampa 4y agoHere's a list of features not supported by Microvium. AFAIK, QuickJS supports all of those (except maybe Intl) https://github.com/coder-mike/microvium/blob/main/doc/supported-language.md#not-supported https://github.com/coder-mike/microvium/blob/main/doc/suppor...
- gigel82 4y agoI don't have anything in Open Source for this, but ran an internal test on a large bundle a while back (7Mb of minified JavaScript with a fairly complex execution pattern) and after the test setup idles, I was seeing 67Mb with V8, 94Mb with Chakra and 109Mb with QuickJS on used memory (also, QuickJs needed a stack increase because it's passing large arguments as values). This was on x64 Windows, it's possible results differ on other platforms.
- edrxty 4y agoSo what's the real use case here? Microcontrollers are generally pretty single purpose, you aren't exactly swapping apps in and out of them like you are with phones. Anything that needs that functionality is using an embedded CPU (MPU) with an MMU rather than an MCU. There are plenty of languages that are better for MCU development than JS so your main use case would be interop with something JS is good for...like a web page served on the device. This is actually not super uncommon but you'd need to be able to interface with some really awful Wifi/Eth drivers that MCUs tend to use so you're still knee deep in C.
- woojoo666 4y agoIs it not enough for people to simply like coding in JS? I like the future that we are moving towards where people can code in the languages they like, irrespective of the platform they are targeting. Just look at the possibilities that WASM has opened up
- edrxty 4y agoWell, I've seen someone build a web scripting engine that parsed C because they really just liked C for whatever reason. I guess a better way of putting this is, with this at the top of HN, what are people excited about building in this?
- pelorat 4y agoWell, hopefully WASM will lead to JS dying out.
- iamsaitam 4y agoNothing would be gained with that
- neilalexander 4y ago> Is it not enough for people to simply like coding in JS? Irrespective of whether people _like_ a language, there are other considerations when evaluating whether something is the best tool for the job. JavaScript has an entire class of bugs in the form of countless unexpected type coercions and equality behaviours that simply don't exist in more compact statically typed languages that would typically be used to target the average microcontroller. When deploying something to the edge, where it becomes significantly harder to maintain, I would want the least surprising behaviour in the language as possible.
- aliswe 4y agoI totally appreciate the effort, but without a runtime parser you're essentially compiling the JS to another language, and then running it with a non-standard engine? Couldnt we simply compile a JS file through eg LLVM to a normal binary, in that case?
- jpgvm 4y agoNot really. It's using a bytecode IR (intermediate representation). An IR is effectively a mid-point between JS and machine code. The benefit of using it is a) it's generally executable by the interpreter with minimal processing b) it's still architecture independent so you can ship the same bytecode to multiple different MCUs. Fundamentally though it's just JS in a different representation rather than a "different language". You probably could generate machine code directly. You can do this already (but generating large binaries unsuitable for embedded) with tools like GraalVM/SubstrateVM. It's actually a fairly difficult problem though due to nature of escape analysis and other things needed to compile highly dynamic languages efficienty.
- jbverschoor 4y agoFake news… just a bytecode runner
- ngcc_hk 4y agoIt is really amazing. When I am young my top boss recalled his day of 4 KB ram mainframe and use eyeball to debug. Then we have 640 kb is all we need era. Up to now, it is easy to use 2GB for a hello world I always think. But this … We are not totally lost.
- nahuel0x 4y agoThe ffi in mJS is something that would need to be a built-in in most engines but Microvium’s unique snapshotting approach makes it possible to implement the ffi as a library just like any of the other functions There is a description of this interplay between snapshotting and FFI?
- codermike 4y agoI think a proper FFI library should be distributed with Microvium for convenience, but I just haven’t gotten around to it yet. But let me try summarize how snapshotting relates.. The snapshotting paradigm means that your JS code starts executing at “compile time” and has access to the compile-time host. Microvium by default provides access to the built-in node modules while the script is executing at compile time (these become detached at runtim), so the JS code can do things like fs.writeFileSync to code-generate C code at compile time. This means you can have a higher-level library that wraps the built in vmExport/vmImport functions while simultaneously generating the corresponding glue code.
- codermike 4y agoBy the way, if you’re interested, I’m the guy behind Microvium. It’s been my pet project for the last few years. It’s very motivating to see all the positive and encouraging feedback. Thank you all! You can find me @microvium on twitter
- Ciantic 4y agoGreat! Your post didn't link directly to Microvium, so I give it here: https://microvium.com/ https://microvium.com/ https://github.com/coder-mike/microvium https://github.com/coder-mike/microvium
- lapser 4y agoWhat would be involved to create a Electron and/or Node alternative with an engine like this?
- steve918 4y agoElectron is kind of a non starter because the hard part isn't the JS interpreter it's the renderer. Node alternative? Fairly trivial, but then you're missing NPM, and pretty much everything else that makes Node not a toy language.
- codermike 4y agoIf by "like this" you mean with snapshotting (e.g. if you prefer snapshotting to bundling https://coder-mike.com/blog/2020/05/15/snapshotting-vs-bundling/ https://coder-mike.com/blog/2020/05/15/snapshotting-vs-bundl...), then node doesn't support it because V8 doesn't (yet) support it, but it might be coming! If by "like this" you mean runs on small devices, maybe check out https://www.neonious-iot.com/lowjs/ https://www.neonious-iot.com/lowjs/
- hiisukun 4y agoI enjoyed the smoke video header on top of your website - I love animations that loop but I can't see exactly where the join is!
- ithkuil 4y agoNice! A few years ago I took a stab at this problem space with https://github.com/cesanta/v7 https://github.com/cesanta/v7 ; with fun tricks like in-place compacting GC, stdlib JS object graph "frozen" in rom etc
- FpUser 4y agoI am not sure of a practicality of JS Engine on those tiny microcontrollers. But I absolutely salute the author for squeezing so much features in so little space. This requires some very serious programming skills.
- larsrc 4y agoI see the lack of runtime parsing as a security feature.
- rambojazz 4y agoWhat is the target market? Do micro-controllers need a JavaScript engine?
- hexo 4y agoNo, MCUs needs a lot better things. I find this only as a curiosity. A nice excercise, nothing more.
- hinkley 4y agoWorking with J2ME many years ago, I ran into a form of scalability issues I hadn’t seen that often before, which is how well can you scale something down, rather than up. I kept having to reimplement things that the JDK had, and with such a small payload size that hurt my budget quite a bit. At the time it was starting to become popular to try to make self-hosted VMs, where parts of the JIT were written in the language instead of C code. We also see languages cycle through a fast interpreter to a fast but sloppy JIT and a slow but effective one. There is still a question from that era that I haven’t been able to explore, and that is what is the distance from a VM that is suitable for embedded work and one that is suitable as the kernal for a JIT. My suspicion is that it’s 10%, perhaps extending to 20% once you start trying to attain very high performance.