7 ms·
We built a background daemon as a macOS menu bar app in Go, and the performance was surprisingly bad. The Go bindings for native UI frameworks ended up being ma
by mnafees 10mo ago
We built a background daemon as a macOS menu bar app in Go, and the performance was surprisingly bad. The Go bindings for native UI frameworks ended up being massive RAM hogs. When we profiled it, we found that the GC essentially gave up under load, which explained why customers were reporting a simple menu bar app consuming 2.5GB+ of RAM on their Macs. We eventually abandoned the Go approach and switched to Electron. (Not-so) Surprisingly, both the DX and UX improved significantly for our use case. Personally, I’d still prefer Swift/C#/C++ for native desktop work (coming from a Qt C++ background), but given the business constraints at the time, Electron ended up being the most pragmatic choice.
- arghwhat 10mo ago> When we profiled it, we found that the GC essentially gave up under load Hmm, the Go GC is really quite capable, so I wonder what kind of pathological load it was being presented with. Even then, when the GC "fails" it means elevated CPU load from collection. The main thing I can think of would be the application "leaking" by having unintentional references (or worse, actually leaking through cgo bindings), or trashing the allocator to cause temporary spikes in between cleanups. However, while I don't think Go was actually to blame here, I would never use native UI bindings to a language that isn't 1:1 compatible with the original design and memory management principles, as such bindings get disproportionaly large and complex. It just sets you up for a bad time.
- mnafees 10mo agoI totally agree :) I don't blame Go either. We were already a pure Go shop with a lot of focus on backend and infra systems engineering and were trying to venture into the desktop app market for our device monitoring software. Once we validated our idea with a rather buggy MVP haha, we quickly switched over to Electron and deployed on all 3 desktop OSes properly.
- ohboybotagain 10mo ago[dead]
- lenkite 10mo ago> The Go bindings for native UI frameworks ended up being massive RAM hogs. Which bindings did you use ?
- mnafees 10mo agoBeen a while since I worked on it but I remember we used https://github.com/getlantern/systray https://github.com/getlantern/systray at some point along with some interaction with fyne.io AFAIR.
- jdndbdhd 10mo agoNot wanting to discredit your experience, but that sounds very strange. This sounds to me like leaking resources from the binding. Which binding did you use and how did you manage it's lifetime?
- mnafees 10mo agoI remember we used https://github.com/getlantern/systray https://github.com/getlantern/systray at some point along with some interaction with fyne.io. That said, I do not remember how we managed the lifetime but we did test it thoroughly before deploying to our initial beta users (or so we thought :P). The GC behavior started to happen whenever the app was in the background, which it was supposed to be for the majority of the time.
- lioeters 10mo agoThat is a surprising use case about Go and Electron (!), I would have imagined no contest for the superior performance of a compiled language, even with garbage collection. But the mention of "bindings for native UI frameworks", it was probably running the compiled code in a very tight loop, stressing the runtime. In contrast, Chromium specializes in UI with years of optimization. Recently for a specific purpose I was reviewing options including Tauri, various WebView bindings, and in the end had to admit that Electron is probably the best approach in terms of feature set, development speed, etc.
- deleted 10mo ago[deleted]
- leeman2016 10mo agoI actually did something similar: business logic and most things written in Go, but the menu bar or tray icon done in native APIs like Win32 and Gtk. It was surprisingly very good experience overall. I have tried so many ways around it before settling for that.
- mnafees 10mo agoVery interesting! How would the Electron and Go processes communicate in this case? Did you expose a Unix socket or TCP port perhaps?
- leeman2016 10mo agoOhh, my apologies for the confusion. I was just using Go as a menubar/tray icon application (with some OS-specific bindings) and meant to say that its performance was excellent. No electron involved