July 30th, 2024

Porffor: A from-scratch ahead-of-time JS engine

Porffor is an experimental JavaScript engine that compiles code to WebAssembly or native binaries, achieving significant size and performance improvements, but is currently intended for research purposes only.

Read original articleLink Icon
ExcitementSkepticismCuriosity
Porffor: A from-scratch ahead-of-time JS engine

Porffor is an experimental JavaScript engine, compiler, and runtime designed to compile JavaScript code to WebAssembly (Wasm) or native binaries ahead-of-time (AOT). Currently, it is intended for research purposes and is not suitable for serious use due to its limitations. The engine's Wasm output is significantly more efficient than existing JavaScript to Wasm projects, being 32 times smaller and 18 times faster than Javy, with sizes reduced from approximately 1.3MB to around 40KB and performance improvements from 70ms to 4ms.

In terms of native compilation, Porffor achieves over 1000 times smaller binary sizes, reducing from about 90MB to less than 50KB, and decreases memory usage by more than 40 times, from 50MB to around 1MB, while also enhancing performance by up to three times. Porffor is designed with safety in mind, as it compiles to Wasm and is built using a memory-safe language. It is developed from scratch with AOT principles, relying solely on a JavaScript parser and supporting TypeScript input without requiring a cumbersome transpilation step. The engine is tested against the official ECMAScript conformance test suite, Test262, to monitor its conformance progress with each commit. Users can experiment with Porffor online or install it locally via npm.

Related

Orb: Write WebAssembly with Elixir

Orb: Write WebAssembly with Elixir

Orb leverages Elixir's ecosystem to simplify WebAssembly writing, offering features like composable modules, Hex package manager, ExUnit testing, macros, and syntax highlighting. It enables Elixir code compilation to .wasm, supports reusable modules, and integrates existing Elixir libraries for MIME tasks, showcasing flexibility in WebAssembly development.

Show HN: Simulating 20M Particles in JavaScript

Show HN: Simulating 20M Particles in JavaScript

This article discusses optimizing JavaScript performance for simulating 1,000,000 particles in a browser. It covers data access optimization, multi-threading with SharedArrayBuffers and web workers, and memory management strategies.

Dynamic Translation of Smalltalk to WebAssembly

Dynamic Translation of Smalltalk to WebAssembly

The article explores Smalltalk code translation to WebAssembly (WASM) within the Catalyst project. It details levels of Smalltalk, JavaScript, and WASM, focusing on direct Smalltalk to WASM optimization. A new translator, WATCompiledMethodTranslator, aids in this process, exemplified by a Smalltalk expression conversion. Creation of a WASM module for Smalltalk methods is explained, highlighting performance advantages and potential future comparisons with dynamic JS translations. Collaboration in the Smalltalk community is encouraged for further advancement.

Show HN → Parallel DOM: Upgrade your DOM to be multithreaded

Show HN → Parallel DOM: Upgrade your DOM to be multithreaded

Parallel DOM accelerates web apps by parallelizing heavy DOM tasks. It integrates easily, runs React components concurrently, and ensures security through sandboxed iframes. Users can self-host or deploy with Vercel.

Baby's Second WASM Compiler

Baby's Second WASM Compiler

A new wasm compiler named zest is under development for 2024, focusing on quality and speed enhancements. It supports various features and employs a tree structure for expressions, emphasizing efficiency and simplicity.

AI: What people are saying
The discussion around the Porffor JavaScript engine reveals several key themes and points of interest among commenters.
  • Excitement about Porffor's potential, especially with the main developer committing full-time to the project.
  • Concerns regarding performance limitations of JavaScript and the challenges of maintaining compatibility with fast-evolving standards like TypeScript and V8.
  • Comparisons to other JavaScript engines, particularly Static Hermes and QuickJS, highlighting differences in output capabilities and design approaches.
  • Curiosity about the handling of runtime features like `eval` and the implications for performance and security.
  • General interest in the future of JavaScript engines and their ability to compile to native binaries or WebAssembly.
Link Icon 24 comments
By @awesomekling - 3 months
Oliver (the main developer) just announced that they’re going to work full time on Porffor: https://x.com/canadahonk/status/1818347311417938237
By @obviouslynotme - 3 months
I have thought about doing this and I just can't get around the fact that you can't get much better performance in JS. The best you could probably do is transpile the JS into V8 C++ calls.

The really cool optimizations come from compiling TypeScript, or something close to it. You could use types to get enormous gains. Anything without typing gets the default slow JS calls. Interfaces can get reduced to vtables or maybe even straight calls, possibly on structs instead of maps. You could have an Int and Float type that degrade into Number that just sit inside registers.

The main problem is that both TS and V8 are fast-moving, non-standard targets. You could only really do such a project with a big team. Maintaining compatibility would be a job by itself.

By @rubenfiszel - 3 months
At windmill.dev, when users deploy their code, we use Bun build (which is similar to esbuild) to bundle their scripts and all their dependencies into a single js file to load which improve cold start and memory usage. We store the bundle on s3 because of the size of the bundles.

If we could bundle everything to native that would completely change the game since as good as bun's cold start is, you can't beat running straight native with a small binary.

By @syrusakbary - 3 months
It's awesome to see how more JS runtimes try to approach Wasm. This project reminds me to Static Hermes (the JS engine from Facebook to improve the speed of React Native projects on iOS and Android).

I've spent a bit of time trying to review each, so hopefully this analysis will be useful for some readers. What are the main commonalities and differences between Static Hermes and Porffor?

  * They both aim for JS test262 conformance [1]
  * Porffor supports both Native and Wasm outputs while Static Hermes is mainly focused on Native outputs for now
  * Porffor is self-hosted (Porffor is written in pure JS and can compile itself), while Static Hermes relies on LLVM
  * Porffor currently doesn't support async/promise/await while Static Hermes does (with some limitations)
  * Static Hermes is written in C++ while Porffor is mainly JS
  * They both support TypeScript (although Static Hermes does it through transpiling the TS AST to Flow, while Porffor supports it natively)
  * Static Hermes has a fallback interpreter (to support `eval` and other hard-to-compile JS scenarios), while Porffor only supports AOT compiling (although, as I commented in other thread here, it maybe be possible to support `eval` in Porffor as well)
In general, I'm excited to see if this project can gain some traction so we can speed-up Javascript engines one the Edge! Context: I'm Syrus, from Wasmer [3]

[1] https://github.com/facebook/hermes/discussions/1137

[2] https://github.com/tc39/test262

[3] https://wasmer.io

By @brundolf - 3 months
There's a subset of JS that's trivially compilable, it's the long tail of other stuff that's hard. But cool to see research happening on where that boundary lies and how much benefit can be had for that subset
By @vanderZwan - 3 months
I unironically appreciate that it supports String.blink. It's always a good sign if the developer has a sense of humor and playfulness.
By @CharlesW - 3 months
What subtleties am I missing that makes "ahead-of-time JS engine" a better description than "JS-to-Wasm compiler"? (If it's mostly a framing strategy, that's cool too.)
By @nick_g - 3 months
I'm a bit suspicious of the versioning scheme described here[0]

If some change were required which introduced a regression on some Test262 tests, it could cause the version number to regress as well. This means Porffor cannot have both a version number which increases monotonically and the ability to introduce necessary changes which cause Test262 regressions

[0] https://github.com/CanadaHonk/porffor?tab=readme-ov-file#ver...

By @mproud - 3 months
“Purple” in Welsh
By @Sytten - 3 months
Its refreshing to see all the various JS engines that are out there for various usecases.

I have been working on providing quickjs with more node compatible API through llrt [1] for embedding into applications for plugins.

[1] https://github.com/awslabs/llrt

By @xyproto - 3 months
Promising, but a few rough edges.

> 1+1

2

> help

Uncaught ReferenceError: help is not defined at exports.<computed> [as main] (file:///opt/homebrew/lib/node_modules/porffor/compiler/wrap.js:494:19) at REPLServer.run (file:///opt/homebrew/lib/node_modules/porffor/runner/repl.js:98:27) at bound (node:domain:432:15) at REPLServer.runBound [as eval] (node:domain:443:12) at REPLServer.onLine (node:repl:927:10) at REPLServer.emit (node:events:532:35) at REPLServer.emit (node:domain:488:12) at [_onLine] [as _onLine] (node:internal/readline/interface:416:12) at [_line] [as _line] (node:internal/readline/interface:887:18)

By @userbinator - 3 months
Porffor can compile to real native binaries without just packaging a runtime like existing solutions.

Any language that allows generating and interpreting its own code at runtime will have the "eval problem". From some other comments here, it sounds like Porffor's solution is to simply ignore it.

By @rvnx - 3 months
Seems like the same idea that Facebook had with PHP which was to transpile PHP to C.

It was called hiphop-php, then they eventually gave up, before creating hhvm on a complete new concept.

By @ijustlovemath - 3 months
I'd love to know if there's a way to compile NodeJS to native libraries with this! I have a process [0], but it's a bit hacky and error prone

[0] - https://github.com/ijustlovemath/jescx

By @giancarlostoro - 3 months
The most interesting bit about Porffor in my eyes is it lets JavaScript compete with something like Blazor (or allows JS to stand its ground), which kind of makes using any JS in your project redundant, since all your front-end logic can be done in C#. The reason I say this is, because obviously, there are JS devs, but if WASM tooling in other languages grows it will make JS redundant or feel incomplete / outcompeted.

I wont be surprised to see a SPA framework that uses Porffor once it is more mature, or even the major ones using it as part of their tooling.

WASM is the next step after SPA's essentially.

If you have never touched Blazor, I recommend you check it out via youtube video if you don't do any C#, it is impressive. Kudos to Microsoft for it. I have had 0 need or use for JavaScript since using it.

By @FpUser - 3 months
I find this very interesting. Keep it up and bring it to production shape
By @solumos - 3 months
Just out of curiosity, how does the performance (compilation + runtime) compare to something like bun[0]?

[0] https://bun.sh/

By @Borkdude - 3 months
I got "TodoError: no generation for ImportDeclaration!" for this script:

import * as squint_core from 'squint-cljs/core.js'; console.log("hello");

By @WatchDog - 3 months
How does this compare to quickJS, which can also compile JS to native code(with a C compiler)
By @saagarjha - 3 months
What happens when someone calls eval?
By @THBC - 3 months
This seems like an opaque supply chain attack waiting to happen.
By @xiaodai - 3 months
Stop trying to retrofit garbage on garbage. Go direct to WebAsm already