Repository navigation
Should vfox-plus go with mygo, still the implementation with the lowest memory usage? #11
Copy link
Copy link
Closed
Labels
questionFurther information is requestedFurther information is requested
Description
- For TODO for the initial release of
version-fox/vfox-plus#3 and [Feature]: Using GUI to manage SDK versions vfox#371 . - With Add Tauri, Wails, Compose, Dioxus, Capacitor, Flet, Gio and Uno implementations #4, Add the mygo implementation #13, Lower the memory of Capacitor, Tauri, Dioxus, Wails and Uno #20, Lower the memory of Compose, Flutter, Flet, Gio, Tauri, Dioxus, Wails and Capacitor #22 and Update the dependencies of every implementation #31 merged,
mainhas ten implementations of the same Linux desktop app: Flutter, the eight other stacks from Impl the WebUI and desktop app for vfox using multiple technology stacks, based on the Material Design 3 Expressive design language #1 and mygo, which yeshan333 suggested below. They follow the same spec and share the translations, icons and test fixtures, so their memory usage can be compared on equal terms. Lower the memory of Capacitor, Tauri, Dioxus, Wails and Uno #20 turned off GPU-dependent rendering in Capacitor, Tauri, Dioxus and Wails and switched Uno to Native AOT, closing most of the gap to mygo, and Lower the memory of Compose, Flutter, Flet, Gio, Tauri, Dioxus, Wails and Capacitor #22 lowered eight of the ten again (Compose from 253 to 129 MB, Flutter from 339 to 172, Wails from 341 to 223). Update the dependencies of every implementation #31 updated the dependencies and toolchains of every implementation. mygo still uses the least memory by a clear margin: 41 MB, which is under half of the 98 MB of Uno, the second-lowest, and under a sixth of the 267 MB of Capacitor, the highest. Should we go with mygo for the initial release? Or is something else more important than memory here, like Wayland support, an Android client or how much UI code we would have to maintain ourselves? - The numbers are from https://github.com/version-fox/vfox-plus/blob/7a24e999fed701d97ba3ac57846380237df1ce81/docs/memory.md . Memory is in MB, for the app and all of its child processes, sorted by the PSS of the home page. "Versions" is the SDKs page with the 872 available versions of Node.js listed.
| Implementation | Technology | Processes | Home PSS | Home RSS | Versions PSS | Versions RSS | The list adds (PSS) |
|---|---|---|---|---|---|---|---|
| mygo | mygo 0.6, Go 1.27.3, GTK 3 (purego), CPU renderer | 1 | 41 | 54 | 47 | 60 | +6 |
| Uno | Uno Platform 6, C# on .NET 10, Skia on the CPU, Native AOT | 1 | 98 | 106 | 113 | 122 | +15 |
| Compose | Compose Multiplatform, Kotlin on JDK 25.0.5+8, Gradle 9.8.2, Skia on the CPU, C1 only | 1 | 129 | 135 | 152 | 158 | +23 |
| Gio | Gio, Go 1.27.3, OpenGL ES through EGL | 1 | 165 | 202 | 171 | 208 | +6 |
| Flutter | Flutter 3.47.8, Dart 3.13.7, Skia on the CPU, GTK 3 | 2 | 172 | 212 | 183 | 223 | +11 |
| Dioxus | Dioxus 0.7, Rust, Node.js 24.22.1 front-end build, WebKitGTK, no compositing, DMA-BUF or JIT | 3 | 203 | 385 | 220 | 402 | +17 |
| Tauri | Tauri 2, Rust, Node.js 24.22.1 front-end build, WebKitGTK 4.1 (GTK 3), no compositing, DMA-BUF or JIT | 3 | 208 | 382 | 220 | 394 | +12 |
| Flet | Flet, Python 3.14 in a Flutter application, uv 0.13.5, Skia on the CPU | 2 | 216 | 257 | 224 | 266 | +8 |
| Wails | Wails 3, Go 1.27.3, Node.js 24.22.1 front-end build, WebKitGTK 6.0 (GTK 4), as Tauri, GTK OpenGL off | 3 | 223 | 408 | 237 | 431 | +14 |
| Capacitor | Ionic Vue and Capacitor in Electron, Node.js 24.22.1 front-end build, no GPU process, no V8 JIT | 4 | 267 | 468 | 281 | 487 | +14 |
- How it was measured: Ubuntu 26.04 in Docker, Xvfb at 1280x800, no GPU, and a fake vfox that replays captured output.
shared/tools/measure.shsumsRssandPssfrom/proc/<pid>/smaps_rollupover the process tree of the app once each page has settled. Flutter has no in-app scenario for this, soflutter/tool/measure.pyclicks through its release build with XTEST instead. Pull requests that rebuild an implementation get a comment with the same table, measured on the runners of GitHub, with the difference frommain(Comment the memory of every implementation on pull requests #21). - PSS is the column to compare. RSS counts a shared page once for every process that maps it, which is why Capacitor has 468 MB of RSS but 267 MB of PSS over four processes.
- Without a GPU, everything that draws with OpenGL loads Mesa's llvmpipe, and that memory is in the numbers (the Gio README says it is most of what Gio uses). Uno is set to draw with Skia on the CPU instead; with Mesa's software GL the same Uno build took about 130 MB more. mygo draws on the CPU too, and the app tells GDK not to open OpenGL: the same build took about 78 MB with it and about 43 MB without. Lower the memory of Capacitor, Tauri, Dioxus, Wails and Uno #20 found the same cost in the web views and in Electron, even on pages this size: WebKitGTK enters accelerated compositing mode, and Electron's GPU process opens, unless told not to, and both map Mesa's software GL the same way. Turning that off (
WEBKIT_DISABLE_COMPOSITING_MODE=1before the webview starts,app.disableHardwareAcceleration()before Electron's window) took Tauri from 419 to 275 MB, Dioxus from 427 to 258, Wails from 482 to 346 and Capacitor from 388 to 303; all four now do this. Lower the memory of Compose, Flutter, Flet, Gio, Tauri, Dioxus, Wails and Capacitor #22 went on with these and with the rest, each change measured against the build without it on the same day: Compose draws with Skia on the CPU (-Dskiko.renderApi=SOFTWARE) and runs the JVM with the first compiler of its JIT only (-XX:TieredStopAtLevel=1), about 50 MB each, 253 to 129 MB; Flutter setsFLUTTER_LINUX_RENDERER=softwareand turns Impeller off, 339 to 172 MB and a tenth of the processor time until the Home page, and Flet only needs the variable, about 340 to 216 MB; Tauri, Dioxus and Wails also turn off the DMA-BUF renderer and the JIT of WebKit (WEBKIT_DISABLE_DMABUF_RENDERER=1,JSC_useJIT=false), 262 to 208 and 261 to 203 MB, and Wails keeps GTK 4 from opening OpenGL (GDK_DISABLE=gl,vulkan,GSK_RENDERER=cairo), 341 to 223 MB; Capacitor keeps the GPU and the network service in the browser process and runs V8 in lite mode, 305 to 267 MB and from six processes to four; Gio keeps one copy of the tables of its variable font instead of three and lets its heap grow 25 % between collections, which takes the heap of Go from 57 to 20 MB, inside a number that varies by 20 MB. I found nothing more to take out of mygo and Uno. On Wayland, GDK opens OpenGL for the windows of GTK 3 unless told not to, which Tauri, Dioxus, Flutter and Flet now do (Tauri on a headless sway: 242 MB without it, 207 with it); the table is measured on X11. What is still created without a GPU is the OpenGL contexts of the engine of Flutter and of the processes of WebKit, which cannot start without EGL, and Gio draws with OpenGL, so on a machine with a GPU the numbers of those, and maybe the order, will be different. - Lower the memory of Compose, Flutter, Flet, Gio, Tauri, Dioxus, Wails and Capacitor #22 was not tested with a real GPU, with GNOME or with the bubblewrap sandbox of WebKitGTK (WebKit's source says that it passes the variables on), and the frame rate of the processor renderers of Compose, Flutter and Flet on a large or HiDPI window has not been checked.
- Each row is one run, and the ten were measured one after another with nothing else running. Gio varies by some 20 MB between runs of the same build, and Flutter was measured six times on an earlier day, when its home page PSS ranged from 332 to 342 MB, so a difference of a few MB means nothing. CPU usage has not been measured yet.
- Wails was suggested in [Feature]: Using GUI to manage SDK versions vfox#371 (comment) as a lighter option than Electron. On Linux, now that the GPU-dependent paths above are off everywhere, it is at 223 MB, below Capacitor, which runs in Electron (267 MB, the highest of the ten), as that comment expected, and close to Tauri (208) and Dioxus (203). WebKitGTK 6.0 with GTK 4, which Wails uses, still needs 15 MB more than the WebKitGTK 4.1 with GTK 3 that Tauri uses for the same front end; it was 71 MB more before Wails kept GTK 4 from opening OpenGL. On Windows, Wails, Tauri and Dioxus use WebView2 instead, which none of this covers.
- All ten only run on the Linux desktop for now. None of them has been built for Windows (
.msixbundle) or Android (.apk) yet, which Impl the WebUI and desktop app for vfox using multiple technology stacks, based on the Material Design 3 Expressive design language #1 asks for. As far as I know, mygo is the only one without an Android target, see its known issues. - Known issues of each implementation, as far as I know,
- mygo
- It is young: 0.6.3 at the time of writing, and its API changes. The version is pinned.
- No Android target. It has backends for Linux, Windows, macOS and browsers, and
GOOS=android CGO_ENABLED=0 go buildfails. It does compile to WebAssembly and draws in browsers (this app builds forjs/wasm, 13.6 MB or 3.5 MB compressed, and WebKitGTK shows it), but a browser cannot start vfox. So a web UI, or an.apkthat is a web view around it, would need a remote process runner and an agent on the machine that runs vfox. None of that is written. - Windows: the app compiles for it, but
core, which Gio has as well, assumes Linux where it stops a process, splitsPATH, looks for vfox and keeps the settings.mygo buildmakes an exe and an NSIS installer, not an MSIX, so the.msixbundlewould be packed withMakeAppx.exeof the Windows SDK. Not tried. - Wayland works through GTK 3: on a headless sway the app id matches the desktop entry. Not tried on GNOME.
- mygo registers ATK objects, which GTK bridges to AT-SPI, so Orca should see the window. Input methods are those of GTK 3 (IBus, Fcitx, the Wayland text input). Neither has been tried.
- It renders on the CPU (see above), and its CPU load during animations has not been measured. The slowest frames I saw in the sandbox took 14 to 36 ms.
- Scaling is GTK 3's, whole numbers only. The title bar is the desktop's, not Material 3 Expressive.
- Like Uno and Gio, every Material 3 Expressive control is our own code (
mygo/ui/kit), with the color utilities and the shapes copied from Gio. - On the first start it writes the two icon fonts (36 KB) to
~/.cache/mygo/fonts/, because fontconfig only loads fonts from files.
- Uno
- No Wayland backend. The window is an X11 window, through XWayland on a Wayland desktop. The display scale comes from
Xft.dpiorUNO_DISPLAY_SCALE_OVERRIDE, and without either it is drawn at scale 1. Only scales 1 and 2 have been tried. - Screen readers cannot see the window, because Uno's X11 host does not talk to AT-SPI. Keyboard navigation works.
- Uno's X11 host supports IBus and Fcitx, but neither has been tried.
- It renders on the CPU (see above), and its CPU load during animations has not been measured.
- Uno's themes do not look like Material 3 Expressive, so every Material 3 Expressive control is our own C# code on WinUI's panels, including ports of the Material color utilities and of
androidx.graphics.shapes. - Once, in a sandbox run under heavy load, part of the previous page stayed on screen after a page switch and a rail expansion. It did not happen again in about 8 later runs.
- No Wayland backend. The window is an X11 window, through XWayland on a Wayland desktop. The display scale comes from
- Gio
- No AT-SPI either, so screen readers cannot see the window. Keyboard navigation works.
- GNOME on Wayland leaves the title bar to the app, so the app draws its own. Double-clicking it does not maximize the window, because Gio hands the press to the compositor for the move.
- Noto Sans CJK only has Regular and Bold, so Chinese text in the other weights of the type scale uses the nearest one.
- Input methods only work through IBus on X11 and
text-input-v3on Wayland. - Like Uno, every Material 3 Expressive component is our own code (
gio/ui/kit), with Go ports of the color utilities and the shapes.
- Compose
- AWT makes it an X11 window, so it also runs through XWayland on a Wayland desktop.
- It renders on the CPU and compiles with the first compiler of the JIT only (see above), which took about half of its processor time in the sandbox. Its frame rate on a large or HiDPI window has not been checked.
- Flutter
- The second process is
glycin-svg, which gdk-pixbuf starts to load the SVG icon of the window. It takes 18 MB of RSS, and without that icon (the desktop entry gives the window its icon once the package is installed) the application would take about 18 MB less, in one process. - It renders on the CPU with Skia (see above), and its frame rate on a large or HiDPI window has not been checked.
- The second process is
- Flet
- It renders on the CPU with Skia too, through a patch of the cached Flet build template, and its frame rate has not been checked either.
- Resizing the window at run time crashes the renderer from time to time on an X server without a window manager (seen under Xvfb). As a workaround, the cached Flet build template is patched so that the window opens at 1280x820 and never resizes itself at start-up.
flet buildhas no offline mode, so a build always needs the network.- Flet only has Flutter's Material widgets, so the Material 3 Expressive parts are in our own Flet extension (
flet/m3e, Python and Dart). It has to stay on Flet's Flutter 3.44.8, while the Flutter implementation is on 3.47.8.
- Capacitor
- Capacitor has no Linux platform, and its community Electron platform only supports Capacitor 5 and has not been updated since 2023. So on Linux this is Ionic Vue in an Electron shell of our own, with one Capacitor plugin as the bridge to the main process.
- The
.tar.gzcannot keepchrome-sandboxsetuid root. After unpacking it, users needsudo chown root:root chrome-sandbox && sudo chmod 4755 chrome-sandbox, orvfox-plus --no-sandbox. - Text fields in dialogs keep Ionic's outlined style under their floating labels, while the other text fields are filled as in Flutter.
- The GPU and the network service run inside the browser process (
--in-process-gpu,NetworkServiceInProcess2), so a failure in either one is a failure of the app, and V8 leaves out its optimizing compiler (--js-flags=--lite-mode). Only the pages of this app have been tried with that.
- Tauri and Dioxus
- Nothing known beyond what WebKitGTK costs for the long list (+12 MB for Tauri, +17 MB for Dioxus, now that accelerated compositing is off).
- Their WebKit runs without its JIT and without the buffers that it shares with the GPU (see above). The end-to-end scenarios pass and the responsiveness did not change in them, but only the pages of this app have been tried.
- Wails
- Wails 3 is still in beta (
v3.0.0-beta.34here). - GTK 4 draws with Cairo and without OpenGL (see above), and WebKit has the settings of Tauri and Dioxus.
- WebKitGTK 6.0 confines its web processes with bubblewrap, which needs user namespaces. CI and the Docker sandboxes do not have them and set
WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1, so the confined mode, which is what users get on a desktop, is not covered by any test.
- Wails 3 is still in beta (
- mygo
- On the license requirement of Impl the WebUI and desktop app for vfox using multiple technology stacks, based on the Material Design 3 Expressive design language #1: Tauri and Dioxus ship
option-ext(MPL-2.0) throughwry. Capacitor ships Chromium's FFmpeg (libffmpeg.so, LGPL-2.1). Flet ships the Dart packagesdbus,nmandupowerand the Python packagecertifi(all MPL-2.0), which Flet itself pulls in. Compose ships a Java runtime made with jlink (OpenJDK, GPL-2.0 with the Classpath Exception). Gio, Uno and mygo have no copyleft dependency (mygo loads the GTK 3 of the system, which is under the LGPL, and does not ship it).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
questionFurther information is requestedFurther information is requested
Activity
linghengqian commentedon Oct 18, 2026
I’d like to open this up for a broader discussion. What are your thoughts? CC @zealcc @jan-bar @ShizheChang @yeshan333 @axdank @ahai-code @yanecc @bytemain @Chance-fyi @aooohan .
yeshan333 commentedon Oct 18, 2026
Try mygo?
linghengqian commentedon Oct 18, 2026
On Linux, it seems that for "mygo" to implement the Material 3 Expressive design language, it has to use WebKitGTK. Does this mean that—much like Wails—it ends up consuming over 400 MB of RAM? This is my first time hearing about "mygo"; am I missing something here?I am testing locally.[-]Should vfox-plus go with Uno, the implementation with the lowest memory usage?[/-][+]Should vfox-plus go with mygo, the implementation with the lowest memory usage?[/+]linghengqian commentedon Oct 19, 2026
aooohan commentedon Oct 19, 2026
We only need to support PC ;)
[-]Should vfox-plus go with mygo, the implementation with the lowest memory usage?[/-][+]Should vfox-plus go with mygo, still the implementation with the lowest memory usage?[/+]linghengqian commentedon Oct 19, 2026
main.linghengqian commentedon Oct 24, 2026
linghengqian commentedon Oct 24, 2026