6 ms·
One interesting aspect of webassembly is that it's feasible to do some advanced program-specific architectures. Consider a website whose img src references are
by sillysaurus3 8y ago
One interesting aspect of webassembly is that it's feasible to do some advanced program-specific architectures.
Consider a website whose img src references are not actually strings, but instead are pointers to memory addresses. Your application works like this: When you attempt to dereference the pointer, a page fault fires, which causes the underlying system to load the image from the server. When the loading is complete, your program resumes.
Big deal. But this opens up another interesting avenue: It's very easy to return a different image while you're waiting for the original to load. Meaning there is no async/await -- no waiting at all. You just write code in the natural, blocking way. No callback hell or promise chains.
There are other interesting applications of this too. When you dereference the pointer to the image, you know the user's viewport size. Meaning you know how large the image should be. Therefore the underlying system can automatically request a perfectly-sized image from the server -- or have the server construct it on the fly, then stream it to the client.
You never have to deal with any of this complexity yourself.
The most important area where this type of design is applicable is gaming. You want to stream the exact texture miplevels you need, at an ~infinite level of detail. If you approach a wall, you want to see lots of high resolution wall textures. But when you move away from the wall, that texture data should be freed. The above architecture handles this type of concern automatically.
- NegativeLatency 8y ago> You never have to deal with any of this complexity yourself. Even if you're using a bunch of saas apps to do this stuff it's still added complexity over a regular web page.
- sbjs 8y agoI really don’t see how any of this isn’t already possible in JS? It can be done cleanly to. Take your first example: img.src = placeholderFor(viewport); loadRealImage().then(src => img.src = src); // carry on
- sillysaurus3 8y agoNow, what do you do when you want to return from that function after loadRealImage() finishes? function loadImage(src) { loadRealImage(src).then(img => /*... return img from loadImage ...?*/); } "Just make it an async function." Well yes, but then the async nature contaminates the rest of your code. You have to make sure to set up a toplevel try-catch for every one of your async chains, for example. What do you do when you want to have an async generator? That is, you want to both await on something, and yield N values from the function. JS makes that difficult. There are all kinds of limitations like this, and everyone has their own favorite hacks around them. But they're hacks, not unification. And yes, hacks can be effective, but a unified framework can be tactical.
- nawgszy 8y ago>yield N values from the function const { all, the, values, you, want } = await multiValuedReturn(); ?
- sbjs 8y agoBut sillysaurus3 has a valid complaint about this line of code, that the very next line is completely blocked until multiValuedReturn() completes. A better solution is to not use `await` here, and instead use .then and Promise.all to control execution of several callbacks, while running other code synchronously. I think the problem sillysaurus3 is facing is that he wants complete convenience of the kind that async/await bring, meaning being able to execute code regardless if it finishes now or later, but always pretending that it finishes now. That's just not possible, and for good reason: some things happen now, and some things happen later, and if you need ultra-fine-grained control over what happens when, then you need to be very explicit about what's happening and how and when. It's messy and ugly, and we're working towards cleaning that up, with async/await being a great step forward, but this is inherent to the concepts of sync/async control flow, and the assembly solution is much more of a hack to solve this (if I even understand the solution correctly) than Promise/async/await/etc.
- sillysaurus3 8y ago
- euroclydon 8y ago> Big deal. But this opens up another interesting avenue: It's very easy to return a different image while you're waiting for the original to load. Meaning there is no async/await -- no waiting at all. You just write code in the natural, blocking way. No callback hell or promise chains. I guess. The renderer asks for an image and you provide one. Then you want to provide one again, but this is like following a customer out of your store after the transaction to give him a different product. It’s not exactly some straight up procedural code.
- marcosdumay 8y agoIt's really asking from an abstraction layer with opaque capabilities... Something like the mobile frameworks or Haskell's MTL-style IO.
- brian_cloutier 8y agoCould you give another example of how this would be used? It seems like a cool idea, but I think I'm too stupid to quite understand why yet. > When you attempt to dereference the pointer, a page fault fires, which causes the underlying system to load the image from the server. When the loading is complete, your program resumes. This first half doesn't sound very exciting, this is exactly how your program already works when it communicates with the OS. It's also how co-routines work, this space has already been pretty well explored. > When you dereference the pointer to the image, you know the user's viewport size. Meaning you know how large the image should be. Therefore the underlying system can automatically request a perfectly-sized image from the server This part seems pretty cool, it's not currently easy to reconfigure your OS and have it change the answers it gives you (except in some obvious cases, like changing the file your program is going to read() ). I like the idea of "dynamically reconfiguring the syscalls", but I'm not sure what I would use it for.
- sillysaurus3 8y agoI like the idea of "dynamically reconfiguring the syscalls", but I'm not sure what I would use it for. Exactly this. Little things, like why can't you just write `fs.readFileSync(<server URL>)`? That's all you want to do. You don't want to deal with issuing a fetch call and setting up handlers and so on. That should be abstracted from you. Ad everyone has their own ways of doing this, and you just search for whatever JS lib happens to tickle you that day. It's the opposite of a unified engine model. Why does that matter? Because the easier your code is to write, the faster you can write. And the larger the systems you can create, individually. Since system value scales inversely proportional to the number of people working on it, that means you alone can build something in a few days that would normally take a team of programmers quite a lot longer. Think of it this way. Why bother writing React? There were existing solutions. Yet we all saw what happens when you ignore standard ways of doing things and push for something better. Two specific examples: You want to write blocking code, no callbacks and no awaits, and you want greenthreads. The reason you want this is because your codebase becomes exponentially smaller. And the only way to accomplish this in JS is to essentially write your own programming language on top of JS. Not really a transpiler, but more like an entire scheduler with heap allocated memory and page tables. If that sounds crazy, just imagine how crazy it would've sounded to try to mix HTML inside of javascript before JSX. The central theme here is simplicity and generality. HN's codebase proves what a single dev can achieve when you focus exclusively on these two goals. EDIT: Some design inspiration: https://www.youtube.com/watch?v=Ox2H3kUQByo&t=1340s https://www.youtube.com/watch?v=Ox2H3kUQByo&t=1340s This is one of the few games where Lisp is used, and they show how and why it enables them to do easily what other games struggle to.
- AgentME 8y ago>[dynamic images in general] Canvas elements already exist. >But this opens up another interesting avenue: It's very easy to return a different image while you're waiting for the original to load. Meaning there is no async/await -- no waiting at all. You just write code in the natural, blocking way. No callback hell or promise chains. Can't you use canvas elements from web workers? Or you could post messages to the UI thread telling it to edit the canvas, which should get you the same effect. None of this seems specific to WebAssembly.
- greggman 8y agoI'm not following you at all. What does loading images have to do with WebAssembly? How will you get webassembly to block based on loading an image? Every API in the browser works on events.