It's been a few months since my last post here, so I wanted to write some updates for my framework azul:
While it's not 0.1-ready yet, it's getting there and I hope to release a 0.1 in December this year, possibly a beta in October / November - right now it doesn't look like the project is failing. In terms of performance, my expectations have been met - roughly 1 - 5 ms in terms of frame time and roughly 40MB - 50MB of RAM usage. This is roughly what a regular QT Quick app is using, so I think that's okay in terms of performance.
I also implemented hot-reloading CSS in debug mode (so that you can quickly iterate on the style without having to recompile the entire app) - see this video I made (sorry for the typos, I was a bit excited to see it work properly):
Here's a screenshot (after I fixed the box-shadows ) - right now flex-direction: [row | row-reverse | column | column-reverse]
is implemented and working:
.. and the RAM usage of the above app is ~43MB - 33MB of which is just webrender:
No more fixed positioning or hacky alignment issues, wohoo! Here is the accompanying Rust code (also see the hot_reload.css
file in the same directory)
There are still some text alignment bugs, linear-gradient doesn't quite work as it's supposed to and some crashes regarding OpenGL, absolute / relative positioning + margins / padding are still missing. And the two-way data-binding / implicit layout API still needs work, otherwise implementing custom widgets will be a pain. But otherwise, it's working quite nicely already.
So my goal was to prove that a DOM-like tree approach + CSS don't have to be as heavyweight or slow as Electron or an entire browser. If you implement only a subset of it and care about performance, you can achieve a middle-ground between performance and ease-of-use.
In terms of borrow-checking, working with an immutable tree has turned out very nicely. Since the DOM tree is immutable, I can go wild with pointers and indices, since they are all valid. Right now the DOM is arena-based, so it's one block of contigouus memory, so it's quite efficient in terms of cache locality.
Layout (using the cassowary constraint system) is pretty fast, since cassowary also acts as a cache for layout constraints and variables - the only time that this is really stressed is when the DOM is heavily modified in comparison to the previous frame - because then I need to insert / remove layout constraints, which can cost a bit of performance (and by that I mean a few milliseconds). So the goal is to make that part faster by diffing the DOM and only adding / removing the relevant constraints, not all of them.
Rendering (the real rendering using webrender, not DOM construction) is quite fast too, but webrender has the overhead of 1ms to build and render any frame, so for games, this probably isn't the tool of choice if your frame budget is 16ms. But for a desktop CRUD app that doesn't have to render an entire world with physics and whatnot every frame, I think 4ms frame time is OK.
I am currently building my app (screenshot below) using azul as a way to prove that it can work and to test the API for papercuts (small problems like a type not re-exported correctly or something like that). I hope to finish this app next month, then I'll have more time to focus on finishing azul full-time.
The main benefit I see of azul over QT or something else is that it's pure Rust, you don't need a meta-compiler or a QML runtime or a third-party language (Python / Vala for GTK) to not rip your hair out over the API and azuls API is very idiomatic - for example in order to build a list with 15 items in a DOM, you can now just do (0..15).map(render_my_item).collect()
- which is also more efficent than the procedural way (with a for-loop).
The biggest problem is actually the Rust compile time - waiting 15s for recompilation when you just want to insert a new DOM node or fix a typo is simply frustrating. But since azul is DOM-tree-based, it would be easy to make a XML-like format that can be hot-reloaded in debug mode - just like the CSS and then write a XML-to-Rust translator (for release mode). The important thing is debug mode - I am currently disallowing users to hot-reload in release mode, since that wouldn't make any sense, in release mode the CSS can't be changed.
There have been some feature requests for static CSS typing and a time-travel debugger when I demoed azul at a Rust meetup a month ago - I've kept these thoughts in the back of my head, but they may not make it in the 0.1 release. So yeah, just wanted to write an update on that, cheers.