Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zig0 takes too much RAM to build zig1.o #6485

Closed
ask6155 opened this issue Oct 1, 2020 · 25 comments · Fixed by #13560
Closed

zig0 takes too much RAM to build zig1.o #6485

ask6155 opened this issue Oct 1, 2020 · 25 comments · Fixed by #13560
Labels
stage1 The process of building from source via WebAssembly and the C backend.
Milestone

Comments

@ask6155
Copy link

ask6155 commented Oct 1, 2020

image


Hello,
Due to the recent changes in the internals of the zig compiler, I'm no longer able to build the compiler anymore.
The build fails at 99% where the self hosted component zig1.o is being built
Here's a small snippet

[ 95%] Building CXX object CMakeFiles/zigstage1.dir/src/stage1/util.cpp.o
[ 96%] Building CXX object CMakeFiles/zigstage1.dir/src/stage1/softfloat_ext.cpp.o
[ 97%] Linking CXX static library zigcpp/libzigstage1.a
[ 97%] Built target zigstage1
Scanning dependencies of target zig0
[ 97%] Building CXX object CMakeFiles/zig0.dir/src/stage1/zig0.cpp.o
[ 98%] Linking CXX executable zig0
[ 98%] Built target zig0
Scanning dependencies of target zig_build_zig1
[ 99%] Building self-hosted component /home/me/git/zig/build/zig1.o
allocation failed
make[2]: *** [CMakeFiles/zig_build_zig1.dir/build.make:77: CMakeFiles/zig_build_zig1] Aborted
make[1]: *** [CMakeFiles/Makefile2:107: CMakeFiles/zig_build_zig1.dir/all] Error 2
make: *** [Makefile:149: all] Error 2

I have 4GB of ram on my system and I'd assume it's enough ram to build the zig compiler as I was able to do that before the restructuring. After the commit 0.6.0+f8b3543ca I am unable to build the compiler due to enormous amount of ram that is required.

I'd like to be able to compile the build on my system because it's one the features of the compiler that I liked. Unlike other languages.

@tauoverpi
Copy link
Contributor

Seems to use up to 5.4GiB on the current commit

@Snektron
Copy link
Collaborator

Snektron commented Oct 1, 2020

I've tested around a bit, and using jemalloc or mimalloc seems to improve memory usage quite a bit. You can use those simply by using LD_PRELOAD to override the usual (glibc or musl) allocator while building Zig:

... usual cmake setup
$ LD_PRELOAD=/usr/lib/libjemalloc.so.2 ninja

(substitute ninja with make if you use make instead)

These are the results i've obtained on my machine for building zig:

Allocator Peak memory usage Wall time
jemalloc 5 440 MB 35.06s
mimalloc 5 661 MB 33.29s
glibc 6 260 MB 36.06s
gc 5 922 MB 42.36

And running stdlib tests:
$ LD_PRELOAD=... /usr/bin/time --format="Peak RSS: %M KB, wall time: %e" ./zig test ../lib/std/std.zig

Allocator Peak memory usage Wall time
jemalloc 5 526 MB 31.76s
mimalloc 5 418 MB 30.01s
glibc 5 924 MB 32.53s
gc 5 317 MB 41.34s

update: I've also tested boehm gc. This was not tested using LD_PRELOAD, but by linking with the library and replacing all malloc calls with the gc equivalent.

Also related: #6467

@Snektron
Copy link
Collaborator

Snektron commented Oct 2, 2020

Update on the above: using the Boehm GC with stage 1 reduces the memory usage to 50%
I'm not sure what happened, but i cannot reproduce the previous numbers i had for the other allocators. I've updated with the new values. Sorry to disappoint.

@marler8997
Copy link
Contributor

@ask6155 did you try downloading more ram? Maybe we should add some logic in the build that checks how much ram the system has and automatically downloads more if there isn't enough?

@andrewrk
Copy link
Member

andrewrk commented Oct 4, 2020

Related: #6467

Things are going to get worse before they get better. The current plan is to (1) release 0.7.0 on October 26th and then (2) focus the main efforts of the next release cycle on finishing the self-hosted compiler, which has much better memory utilization. At this point the plan is #6378.

Hang on tight, it's gonna be a bumpy ride. But we'll get through to the other side.

@andrewrk andrewrk added the stage1 The process of building from source via WebAssembly and the C backend. label Oct 4, 2020
@andrewrk andrewrk added this to the 0.8.0 milestone Oct 4, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@abthefish
Copy link

Andrew and all,
I tried to get around the 'allocation failed' error on a vbox Alpine 32b system by increasing swap with a swapfile. I added a 16GB /swapfile to the existing 4G swap partition.

free -m
Mem: 3542
Swap: 20479

I fail with the identical error output as the OP. I have not tried building/loading alternative *malloc libs; my interpretation of Snektron's update is this is (probably?) not an option.

Are there no work arounds to 'Hang on tight' at this point?

Thank you to all who are contributing to ziglang.

FWIW I followed this for the build; llvm v11 built without issue:
https://github.com/ziglang/zig#posix

@jedisct1
Copy link
Contributor

I'd still recommend trying with jemalloc instead of the glibc malloc.

On my router that has a similar amount of memory, I can't build Zig with the default malloc either, but with jemalloc, compilation eventually completes.

@abthefish
Copy link

abthefish commented Nov 10, 2020

Thank your for that clarification. I'll try getting 'jemalloc' on my system.
Update: Nope : ) 'jemalloc' wasn't enough to coerce Zig 0.7 to compile on Alpine 32bit; good luck to the Zig team shrinking the memory footprint in 0.8. I'll 'hang on tight' and look forward to revisiting Zig down the road.

@brentr
Copy link

brentr commented Mar 13, 2021

Zig will not build on any 32-bit system if the process needs >4Gbyte of RAM.
The address space required is > 32-bits
I'd like to play with this cool, new toy, but my 32-bit Linux environment apparently won't cut it.

@brentr
Copy link

brentr commented Mar 13, 2021

I just managed to build zig release 0.71 stage 1 on an 32-bit i386 Debian Bullseye/Sid system.
Here's what worked for me:

 $ mkdir build
 $ cmake .. -DCMAKE_PREFIX_PATH=~/zig -DCMAKE_BUILD_TYPE=Release
 $ make #-j9

This completed in about 3 minutes with a peak resident size of 3.6GB
Alternatively, this:

$ LD_PRELOAD=/usr/lib/i386-linux-gnu/libjemalloc.so.2 make

completed in about the same time with a peak resident size of only 3.2GB

@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
@andrewrk andrewrk changed the title Building the zig compiler fails due to memory allocation failure zig0 takes too much RAM to build zig1.o Jun 6, 2021
@andrewrk andrewrk modified the milestones: 0.10.0, 0.9.0 Jun 6, 2021
@andrewrk andrewrk pinned this issue Jun 6, 2021
@d3dave
Copy link

d3dave commented Aug 12, 2021

I hit OOM when building from master with jemalloc on a machine with ~5GB free. If anyone is still struggling like I was, I finally managed by setting up zram swap on 50% of RAM (~4GB).

@voroskoi
Copy link
Contributor

I have run into this on rpi4 (8GB ram). Adding swap did help.

If You do not know how to add swap this should work (you have to be root for these):

# fallocate -l 4GB /swapfile
# chmod 600 /swapfile
# mkswap /swapfile
# swapon /swapfile

After successful build you can remove the swap:

# swapoff /swapfile
# rm /swapfile

@jedisct1
Copy link
Contributor

zram also helps a lot.

Install zram-tools and set ALGO=zstd in /etc/default/zramswap.

@rahulmutt
Copy link

Out of curiosity, I ran heaptrack for the self-hosted compilation step with the following changes to CMakeLists:

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,6 @@
 cmake_minimum_required(VERSION 2.8.12)

+FIND_PROGRAM(HEAPTRACK_PROGRAM heaptrack)
 # Use ccache if possible
 FIND_PROGRAM(CCACHE_PROGRAM ccache)
 IF(CCACHE_PROGRAM)
@@ -868,7 +869,7 @@ set(BUILD_ZIG1_ARGS
 if("${ZIG_EXECUTABLE}" STREQUAL "")
   add_custom_command(
       OUTPUT "${ZIG1_OBJECT}"
-      COMMAND zig0 ${BUILD_ZIG1_ARGS}
+      COMMAND ${HEAPTRACK_PROGRAM} ${CMAKE_BINARY_DIR}/zig0 ${BUILD_ZIG1_ARGS}
       DEPENDS zig0 "${ZIG_STAGE2_SOURCES}"
       COMMENT STATUS "Building self-hosted component ${ZIG1_OBJECT}"
       WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"

The heaptrack output is attached in this Gist.

@tomoverlund
Copy link

Out of curiosity, I ran heaptrack for the self-hosted compilation step with the following changes to CMakeLists:

I'm working on this issue (I already discussed this with Andrew on Discord). Here's a description of the problem with the proposed solution (in progress):

Recap of compiler stages:

zig0: Stage 0 compiler, consisting of all C++ code.
zig1: Stage 1 compiler, consisting of C++ code and Zig code.
zig2: Stage 2 compiler, consisting of all Zig code.

We are concerned with building zig1 via zig0, which currently takes over 8 gigs. Why does it take so much memory? It is NOT because of memory leaks, nor because of the memory allocator. It's because zig0 compiles the ENTIRE std .zig library into one giant, in-memory object and then creates an executable file from that. That's about 35,000 function definitions.

So the solution: Introduce separate compilation with separate modules, which will then be linked together at the end.

BratishkaErik added a commit to BratishkaErik/gentoo that referenced this issue Mar 24, 2022
see ziglang/zig#6485

Package-Manager: Portage-3.0.30, Repoman-3.0.3
Signed-off-by: BratishkaErik <bratishkaerik@getgoogleoff.me>
BratishkaErik added a commit to BratishkaErik/gentoo that referenced this issue Mar 24, 2022
see ziglang/zig#6485

Package-Manager: Portage-3.0.30, Repoman-3.0.3
Signed-off-by: BratishkaErik <bratishkaerik@getgoogleoff.me>
gentoo-bot pushed a commit to gentoo/gentoo that referenced this issue Mar 28, 2022
see ziglang/zig#6485

Package-Manager: Portage-3.0.30, Repoman-3.0.3
Signed-off-by: BratishkaErik <bratishkaerik@getgoogleoff.me>
Closes: #24734
Signed-off-by: Florian Schmaus <flow@gentoo.org>
@andrewrk
Copy link
Member

We are one major step closer to solving this now that the self-hosted compiler can build itself. The next major step to solving this will be getting the C backend to passing all behavior tests.

@tomoverlund
Copy link

I'll be dropping my efforts on reducing zig0 memory usage then, since it will soon be obsolete if it isn't already.

@tomoverlund
Copy link

By the way, you mentioned in your recent 2023 Roadmap video that building the self-hosted compiler will take about 0.5 GB, but when I built stage 3 from stage 2 it was taking about 2.5GB. Obviously, though, that''s a big improvement from the >8GB.

@andrewrk
Copy link
Member

During that talk we didn't have it fully building yet so I gave a (clearly too optimistic) guess based on how much of the compiler that was being built at the time. I did make sure to qualify my prediction carefully, mentioning that the number could be off from the final value once it is building.

Anyway it can still be improved from this point- this is only the beginning.

@hdante
Copy link
Contributor

hdante commented Jul 17, 2022

Hello, I've noticed that Zig is, right now, in a "package management limbo", where packages are being pulled out of the repositories, apparently because of this issue (out-of-memory when building). I've confirmed that Zig has been removed from OpenBSD 7.1 and Windows MSYS2. Maybe fixes should be backported to the 0.9 release ? For example, version 0.9.2 could be released and maintained for 1 year, while next version is developed with more tranquility.

@hdante
Copy link
Contributor

hdante commented Aug 10, 2022

Hello, are there any updates about this issue ?

@Ristovski
Copy link
Contributor

Ristovski commented Aug 20, 2022

The self-hosted compiler has now been set as the default one, which comes with a set of improvement that are listed in the upgrade guide: https://github.com/ziglang/zig/wiki/Self-Hosted-Compiler-Upgrade-Guide#improvements-over-stage1

One of them is:

Memory usage is improved by a factor of about 3x. For Zig, building itself went from using 9.1 GiB to 2.7 GiB.

..so building Zig yourself should now be generally more approachable even on modest hardware, given you are of course building from master as opposed to stable.

@vt-alt
Copy link

vt-alt commented Jan 21, 2023

[ 99%] Building stage2 object /usr/src/RPM/BUILD/zig-0.10.1/i586-alt-linux/zig2.o
cd /usr/src/RPM/BUILD/zig-0.10.1 && /usr/src/RPM/BUILD/zig-0.10.1/i586-alt-linux/zig1 src/stage1.zig --name zig2 --zig-lib-dir /usr/src/RPM/BUILD/zig-0.10.1/lib -femit-bin=/usr/src/RPM/BUILD/zig-0.10.1/i586-alt-linux/zig2.o -fcompiler-rt -target native -mcpu native -lc --pkg-begin build_options /usr/src/RPM/BUILD/zig-0.10.1/i586-alt-linux/config.zig --pkg-end
allocation failed

What I am doing wrong?

@mlugg
Copy link
Member

mlugg commented Jan 21, 2023

Zig 0.10.1 still includes the old stage1 codebase, and uses it for bootstrapping. This issue is solved in master, and the fix will be in 0.11.0 since master no longer contains the old codebase (the bootstrap process has been replaced), but until then if you want to bootstrap without OOMing you need to use master.

@vt-alt
Copy link

vt-alt commented Jan 21, 2023

@mlugg Thanks for explanations!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage1 The process of building from source via WebAssembly and the C backend.
Projects
None yet
Development

Successfully merging a pull request may close this issue.