from Hacker News

Analysis of the overhead of a minimal Zig program

by matu3ba on 1/2/22, 8:50 PM with 107 comments

  • by moonchild on 1/2/22, 10:58 PM

    No comment on content. However:

    > What's up with the and rsp,0xfffffffffffffff0? That's because the function manually aligns the stack to the next 16-byte boundary. I'm not sure why the stdlib does this. The SystemV ABI (§2.3.1) guarantees an initial alignment of 16 already, so it should be superfluous.

    Linux does not make any such guarantee, however; so in order for _start to call functions using the sysv ABI in a compliant fashion, it must provide them with an aligned stack.

  • by dleslie on 1/2/22, 9:33 PM

    Interestingly, I can't seem to get an empty nim programme below 32k.

       #> touch foo.nim
       #> nim c -d:release --opt:size -d:strip -d:danger foo.nim
       #> ls -lhs foo | cut -d\  -f1
       32K
  • by Sniffnoy on 1/3/22, 3:22 AM

    Related: Just how small can you make an executable on 32-bit Linux? http://www.muppetlabs.com/~breadbox/software/tiny/

    (You'll notice that, despite the change from 32-bit to 64-bit, the figure of 297 bytes mentioned in the OP as how much you'd get from doing everything in assembly and aggressively stripping is the same figure that Brian Raiter comes up with in part III of the Teensy Files, where he attempts to do everything in a totally above-board manner.)

  • by ftrobro on 1/2/22, 9:48 PM

    "Aggressively stripping out all the unnecessary trash that the linker puts into it makes it 297 bytes"

    Reminds me of how impressive 256 byte intros are, like this one:

    https://www.youtube.com/watch?v=w72MXbAIJVg

  • by NikolaeVarius on 1/2/22, 9:42 PM

    > I've watched friends try Go and immediately uninstall the compiler when they see that the resulting no-op demo program is larger than 2 MiB.

    That seems a bit extreme

    > Overhead breeds complacency — if your program is already several megabytes in size, what's a few extra bytes wasted? Such thinking leads to atrocities like writing desktop text editors bundled on top of an entire web browser

    I'm still on board

  • by goodpoint on 1/2/22, 10:12 PM

    This is gold:

    """ Overhead breeds complacency — if your program is already several megabytes in size, what's a few extra bytes wasted? Such thinking leads to atrocities like writing desktop text editors bundled on top of an entire web browser, and I think it would be nice to have a language that pushes people to be a bit more mindful of the amount of resources they're using. """

  • by gbrown_ on 1/3/22, 12:12 PM

    Not sure why the article links to some runtimejs copy of musl [1]. It's quite old (2014 vintage) to the point where the referenced code is no longer present upstream [2].

    [1] https://github.com/runtimejs/musl-libc/blob/master/crt/x86_6...

    [2] https://git.musl-libc.org/cgit/musl/commit/?id=6fef8cafbd0f6...

  • by asdfasgasdgasdg on 1/2/22, 9:20 PM

    It's an interesting analysis, but I'm a little skeptical that there is any partical scenario where Linux would be runnable and a 1.2 kB program will significantly underperform a 600B program. The program would have to be small indeed for this difference to be material.
  • by 3a2d29 on 1/3/22, 2:42 AM

    I've been seeing a lot of posts about Zig recently. Out of curiosity is there a specific reason these are more common (like a recent big project or release)? Not hating, just wondering.

    EDIT: Just saw there was a new release 10 days ago, although it wasn't 1.0

  • by gameswithgo on 1/2/22, 11:55 PM

    The bit about people uninstalling when they see a 2MB no-op demo program is so dumb. That is a fixed cost, its just because Go packages it's runtime in the EXE so you can distribute it and expect it to actually work rather than depending on a runtime being available on the system. Sure there are niche cases where that isn't appropriate, and you don't use Go for those. But that initial 2MB doesn't tell you anything about how program size grows for actual projects.
  • by KronisLV on 1/3/22, 8:03 AM

    > Overhead breeds complacency — if your program is already several megabytes in size, what's a few extra bytes wasted? Such thinking leads to atrocities like writing desktop text editors bundled on top of an entire web browser, and I think it would be nice to have a language that pushes people to be a bit more mindful of the amount of resources they're using.

    You know, reading this kind of hurts. On one hand, i fully agree. If we take something like Visual Studio Code as an example, the folks at Microsoft have seemingly done much of what's possible to make it feel snappy and responsive, sometimes to surprisingly good results, yet i also remember how sluggish Brackets or Atom were as editors, both also based on browser technology.

    On the other hand, i feel that it's not the filesize that developers care about when choosing browser tech, but rather their hands are forced because of a lack of other good options out there. Show me a widely supported cross platform GUI framework that's as easy to pick up and use as Electron's stack for the developers of our current year - people who in many cases don't have years to master many different technologies, but just want/need to apply much of what they already know to deliver software in short amounts of time. For better or worse, browser technologies have become the one common platform, in more ways than one.

    Of course, i'll actually try to answer my own question above. In my eyes, the way how Lazarus/Pascal approached this issue was great: their LCL (https://en.wikipedia.org/wiki/Lazarus_Component_Library) provided a set of common components and then allowed them to target Win32, GTK, Qt, Carbon, ... based on the compile target, while on the tooling side they still had a really great RAD environment, with all of the drag & drop functionality of yesteryear. Now, Lazarus/Pascal are basically dead due to lack of hype/interest in those technologies, but they came pretty close to being the best option out there in my eyes!

    Apart from that, i'm not quite sure. Over the years there have been many attempts at creating cross platform GUI frameworks for .NET, but there's still nothing truly stable yet. In Java, i really liked Swing because it was just so darn functional and simple to implement (with IDEs also having GUI builders), however many rather disliked how it didn't really look or feel native in many cases, which may or may not be relevant for particular types of software. In recent years, there also was JavaFX/OpenJFX (https://openjfx.io/) which i think is a good step in the right direction, but last i checked the tooling wasn't quite there yet - an integrated workflow that just lets you create and drag around windows/components without bothering too much to read the docs, whilst also letting you edit the autogenerated code after a rough wireframing/prototyping pass, should the need arise. In most other tech stacks, like Python, packaging and other concerns can be a mess, as can the loosely coupled tools be cumbersome to work with - sometimes you just want one executable (or close to it) at the end of your build steps, which can run on any supported platform.

    The fact of the matter is, that if there was something easy to use, many would switch away from Electron on a whim. Not everyone is smart enough or has the time to grok lots of different technologies, or learn something a bit lower level like Qt or GTK, which in lieu of bindings for higher abstraction level languages, will typically be used in language with plenty of footguns, avoiding which takes discipline and knowledge. Regardless, not everyone needs the high customizability of the web platform. Sometimes just having native UI components being created from some abstracted common set of components would be fully enough.

    But until technologies that make that easy surface, we'll just keep complaining about Electron every year.

  • by kwhitefoot on 1/3/22, 1:19 PM

    This sort of thing makes me think fondly of using Fortran many years ago (I forget which version).

    Then every subroutine was separately compiled into a separate object file. The linker linked only those that were actually used (if I remember correctly).

    Of course there was no dynamic dispatch so it wasn't difficult to prove what was and wasn't needed.

  • by Thaxll on 1/2/22, 11:53 PM

    I know it's easy to troll on JS but Electron is a very succesful project that lead to softwares used by hundred of millions of people, can't say the same about Zig or its future.
  • by alkonaut on 1/3/22, 12:36 AM

    Launching entire processes to do small operations is an antipattern. Whether a program is 1k or 10k can’t make that much difference if the minimum process spawn time is counted in hundreds of milliseconds? Yes, I know, it’s about the philosophy of unnecessary waste and not actually about the first kb, a philosophy I can certainly support.

    But still, launching a 1MB program and then launching threads from it takes a fraction of the time per thread. The 1MB process start time is quickly amortized.

    I know as he mentions there are situations where small processes are launched hundreds of times, but these days I think of it as a disappearing antipattern. Consider how in the past it was common with compilers to use one process to compile one source file and exit. Or how a web server would serve one request and then exit. There is a reason that went out of fashion.

    So the only time I’d reach for actually making a tiny executable out of performance concerns would be if I couldnt use a fatter binary and I knew the tool (for whatever reason) had to be invoked a lot, and it wasn’t under my control.