# Julia GC, heap fragmentation, out of memory, push!/append!

**URL:** https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224
**Category:** Internals & Design
**Created:** [August 3, 2022, 11:52am UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224 "2022-08-03T11:52:17Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 11:52am UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/1 "2022-08-03T11:52:17Z")

</div>

I saw the juliacon22 video from Christine Flood about Julia GC. I’m glad to see that the GC is finally getting some attention and not just the compiler. It’s long overdue.

Let’s just address the elephant in the room: The Julia GC has a memory fragmentation problem. There I said it. I brought this possibility up (I wasn’t sure at that time) on this forum a few times over the years (all the way back since julia 0.2) but this was always brushed aside. The standard answer seems to be: Julia GC doesn’t have a problem, it’s you (i.e. you have a memory leak). My code didn’t, but proving that was pretty impossible due to the lack of tooling to find memory leaks in user code.

Anyway it’s good to see that Christine finally acknowledged the fact that even without a user memory leak Julia can take more and more of host memory until you run out (I’ve experienced this myself). This is of course heap fragmentiation although she never uses that term. Admitting that you have a problem is the start of recovery 🙂

Unfortunately the immediate things planned seem to be about performance (parallel GC, shorter collect time) rather than fixing fragmentation. Due to the current constraint of non-movable heap memory I’m not sure if this problem can ever be fully solved. To fix it completely you’ll probably have to relax that constraint. Hopefully the future GC work will also try to address (or at least mitigate) fragmentation.

What I do now is adapt my code to avoid fragmentation as much as possible. This is also good for performance. So instead of using push!/append! and only try to use just enough memory as required (like you would in languages like Java/C# with GCs that don’t have fragmentation issues) I preallocate a fixed amount of memory (more than strictly needed sometimes) and initialize everything with zeros. That’s of course an old school trick. That solved an out of memory problem I had in an application.

I feel that in the documentation push! and append! (and similar functions) should have a warning saying that the use of these for large number of elements (tens of thousands) will cause heap fragmentation, slow run time and possibly an out of memory. A warning like “push!/append! considered dangerous” might not be out of place.

Next I’d like to see some tooling that lets you look at the heap structure (like you have for JVM/CLR) and detect where a lot of allocations/deallocations happen from (I believe from one of the presentations there is in the profiler now some info about allocations). Ideally in a graphical way and integrated into the VSCode tooling.

But of course the best solution would be a better GC that does’t take more memory than needed. A region based GC would be sweet!

There is now a new argument to julia for a memory limit. That’s a step in the right direction but it’s not a hard limit so it’s still possible to run out of host memory and crash the host itself. That’s bad for servers! I’d like to see another option that is a hard heap size limit just like for the JVM where it the julia heap would need more than the specified limit it exits with an OutOfMemory exception. So only julia exits cleanly and you host server never crashes. I’ m sure sysadmins will appreciate that 🙂

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 3, 2022, 12:21pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/2 "2022-08-03T12:21:23Z")

</div>

> [@Steven\_Sagaert](#):
>
> So instead of using push!/append! and only try to use just enough memory as required (like you would in languages like Java/C# with GCs that don’t have fragmentation issues)

Could you elaborate on that a bit? How does using `push!`/`append!` lead to fragmentation (of what, exactly)?

---

<div class="post-metadata">

### Author: ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)
#### Post date: [August 3, 2022, 12:22pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/3 "2022-08-03T12:22:45Z")

</div>

Switching to a compacting GC would be awesome, but unfortunately it’s not as simple as one would hope. Ruby changed to one on 3.0 and they faced similar challenges [Ruby Garbage Collection Deep Dive: Compaction | Jemma Issroff](https://jemma.dev/blog/gc-compaction). There is some work, currently a bit stalled, for a heap snapshot feature like you mentioned.

As such improving our current GC is a more viable mid term solution, and it will help in lots of cases.

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 12:30pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/4 "2022-08-03T12:30:10Z")

</div>

It’s simple really: instead of starting with a big array preallocated of zeros and then filling in the actual values, you start with a empty array and push/append values to it (in case you do not know before hand how many it will be). If you have a lot of values (at least ten of thousand and depending on how much ram your machine has) the runtime will have to periodically allocate a bigger array, copy over the existing values and deallocate the old array. Now if you GC doesn’t defragment your heap from time to time , after a while your heap will look like swiss cheese and if then you need to allocate a chunk bigger than the biggest contiguous chunk left in the heap , the runtime will ask the OS for more merory. And so the julia process will grow and grow in absolute memory (what you see with your os tooling like top). Eventually your host is going to run out of memory.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 3, 2022, 12:38pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/5 "2022-08-03T12:38:48Z")

</div>

Ok, you mean fragmentation in the sense that there’s more and more disjoint allocations (from the OS’ POV) that don’t get freed. I’d count that as a memory leak, not as heap fragmentation (which to me is relevant when talking about chasing pointers).

> [@Steven\_Sagaert](#):
>
> Eventually your host is going to run out of memory.

That I find quite unlikely, since all memory allocated is virtual memory anyway. I assume you mean when you finally run out of SWAP as well (in which case you’d OOM either way).

That said - freeing memory that isn’t needed anymore and reusing the chunks would certainly be beneficial.

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 1:35pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/6 "2022-08-03T13:35:52Z")

</div>

No it’s not a memory leak in the strict sense it’s julia heap fragmentation. However it’s an _effective_ memory leak from the OS point of view since all it sees is a julia process that keep on asking more memory.

I meant when your process needs more than available RAM. Yes you could go on using swap space for a while but you definitely don’t want that, your speed would be very slow. Also it’s not a linear progression: at first the GC will be able to cope and free memory and you wan’t see an increase. Everything appears stable and normal but then you see an accelerating increase for memory and larger and larger fluctuations (GC struggling to free enough memory but not quite succeeding) till at the end your process memory is fluctuating very closely to 100 RAM all the time and you process speed grinds to a halt.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [August 3, 2022, 2:28pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/7 "2022-08-03T14:28:32Z")

</div>

Not a solution, but I would point out that languages like C, C++ and Rust do not have any way to defragment their heaps either. Malloc implementations will try to avoid fragmentation, but it can still happen, and in those languages, when it does, it’s on the programmer to figure out how to deal with it.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [August 3, 2022, 2:32pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/8 "2022-08-03T14:32:23Z")

</div>

> [@gbaraldi](#):
>
> Switching to a compacting GC would be awesome,

I think move objects in memory would be terrible for integrating Julia with other languages

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 2:36pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/9 "2022-08-03T14:36:09Z")

</div>

I get that. I wouldn´t move memory held by native code but maybe for pure julia code, so partially relax the no move constraint

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [August 3, 2022, 2:53pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/10 "2022-08-03T14:53:18Z")

</div>

How would that work? Julia already compiles to native code, so regular julia code would have to be treated just the same, no?

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 3:11pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/11 "2022-08-03T15:11:14Z")

</div>

I meant memory held by external libs.

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 3:22pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/12 "2022-08-03T15:22:19Z")

</div>

Yes but in those languages you know that you’re responsible for memory management. In fact in those languages they want to manage all of that explicitely for full control including allocation/deallocation strategies like only use static memory in C for embedded systems or arena allocators in C++ etc. In higher level languages with GC you usually do not want to think too much about that

Right now in the documentation of Julia (AFAIK) there is nothing that says that the GC doesn’t take care of fragmentation and hence that the user should himself think about that and use for example strategies like preallocate as much as possible. Documenting that would be a good first step to handle the problem.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [August 3, 2022, 3:57pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/13 "2022-08-03T15:57:30Z")

</div>

Note that we are actively collecting GC benchmarks at [GitHub - JuliaCI/GCBenchmarks](https://github.com/JuliaCI/GCBenchmarks). If you have good problem cases for GC aren’t yet represented in the test cases we would love PRs.

---

<div class="post-metadata">

### Author: ![Steven\_Sagaert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steven_sagaert/32/29578_2.png) [@Steven\_Sagaert](https://discourse.julialang.org/u/Steven_Sagaert)
#### Post date: [August 3, 2022, 4:07pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/14 "2022-08-03T16:07:10Z")

</div>

When I have some time I’ll try to go back to some old crappy code and extract just the code needed to blow up the memory 🙂

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [August 3, 2022, 4:55pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/15 "2022-08-03T16:55:58Z")

</div>

> [@Steven\_Sagaert](#):
>
> Let’s just address the elephant in the room: The Julia GC has a memory fragmentation problem.

Thanks for bringing it up, but I think it’s a non-issue, or I mean with an alternative allocator a small issue.

It’s time to revisit mimalloc (I looked into linking alternatives to Julia before):

> **[GitHub - microsoft/mimalloc: mimalloc is a compact general purpose allocator...](https://github.com/microsoft/mimalloc)**
>
> mimalloc is a compact general purpose allocator with excellent performance. - GitHub - microsoft/mimalloc: mimalloc is a compact general purpose allocator with excellent performance.

> mimalloc is a drop-in replacement for `malloc` and can be used in other programs without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as:

```julia
> LD_PRELOAD=/usr/lib/libmimalloc.so myprogram

```

> It also has an easy way to override the default allocator in [Windows](https://github.com/microsoft/mimalloc#override_on_windows). Notable aspects of the design include:  
> […]
> 
> - **free list sharding** : instead of one big free list (per size class) we have many smaller lists per “mimalloc page” which reduces fragmentation and increases locality – things that are allocated close in time get allocated close in memory. […]
> - **free list multi-sharding** : the big idea! Not only do we shard the free list per mimalloc page, but for each page we have multiple free lists.
> - **secure** : _mimalloc_ can be built in secure mode, adding guard pages, randomized allocation, encrypted free lists, etc. to protect against various heap vulnerabilities. […]
> - **bounded** : it does not suffer from _blowup_ [1], has bounded worst-case allocation times (_wcat_), bounded space overhead (~0.2% meta-data, with low internal fragmentation), and has no internal points of contention using only atomic operations.
> - **fast** : In our benchmarks (see [below](https://github.com/microsoft/mimalloc#performance)), _mimalloc_ outperforms other leading allocators (_jemalloc_, _tcmalloc_, _Hoard_, etc), and often uses less memory. A nice property is that it does consistently well over a wide range of benchmarks. There is also good huge OS page support for larger server programs.

The thing is when I tried it, it surprisingly didn’t help, but that’s because each allocation in Julia doesn’t directly lead to malloc in C. Julia does something similar, tries to allocate its own larger blocks (to reduce fragmentation, just likely not in a state-of-the-art way, that seems to be it, and I’m not sure it conflicts with our GC). I didn’t look into bypassing that, but would likely be great, as simplifying Julia’s codebase, and opting into this 8k LOC library (which might be larger than the code we eliminate, but still a win, then not part of our codebase).

Bypassing (eliminating) the Julia code, as also great because then we can try other options too, not just the devs, but also users, choosing the alternatives with LD\_PRELOAD above, since:

> General memory allocators are interesting as there exists no algorithm that is optimal – for a given allocator one can usually construct a workload where it does not do so well. The goal is thus to find an allocation strategy that performs well over a wide range of benchmarks without suffering from (too much) underperformance in less common situations.

> [@Steven\_Sagaert](#):
>
> Due to the current constraint of non-movable heap memory I’m not sure if this problem can ever be fully solved.

I’m skeptical that’s the solution. Moving stuff around means ~~actual copying~~ (EDIT: usually, not always see MESH allocator in my post below) and CPU/RAM bandwidth overhead, while, yes eliminating fragmentation, but the fragmentation we do have, and will not eliminate completely (just reduce), is in virtual space (mostly), which is free? It used to be a limited resource too (in 32-bit era, we shouldn’t optimize for that), but in 64-bit it’s at least close to free. I’m not sure where the holes in address space end up, if in a swap file, then that’s just stupid. This is a solved problem for sparse files, so I doubt it’s done that way.

From memory (and claim above), that’s likely the best alternative malloc alternatice, but see also my older thread:

> [@Julia vs Microsoft's (Rust-inspired) Verona language and e.g. snmalloc allocator](https://discourse.julialang.org/t/julia-vs-microsofts-rust-inspired-verona-language-and-e-g-snmalloc-allocator/38610):
>
> The research project doesn’t mean “Microsoft is no longer using C++/C#/Rust”. See under C. The project is meant to be learned from, to integrate the ideas into other languages. I’m not sure if it’s possible to add to Julia their “new concurrency model that seamlessly integrates ownership.” Still, it seems we could reuse their new allocator for a performance benefit. A. The allocator is intriguing “enables 1000s of remote deallocations to be performed with only a single atomic operation enabli…

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [August 3, 2022, 5:14pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/16 "2022-08-03T17:14:22Z")

</div>

> [@gbaraldi](#):
>
> Switching to a compacting GC would be awesome

As I said, I’m not sure, I didn’t yet read the Ruby … Deep Dive, I guess it does help most far small objects, because of cache issues, not (huge) arrays of small, i.e. matrices Julia is most optimized for. At least I would first look into the simple change I proposed, and as a last resort, compacting, or a hybrid solution. If the small objects would most likely be strings, then those oare object very likely to be passed to or from e.g. C. For interop you can’t use compacting, so it seems then the user would have to predict which objects, e.g. `String`s will be passed to C (as `CString`).

I note from the Deep Dive (outdated?):

> It’s important to also note that as of Ruby 3.0, compaction is still under development and actually currently degrades performance on most apps. It’s therefore not automatically turned on.

You might think with the blog post from May 2021 and Ruby 3.0 rather recent they went with good algorithms, something recent, but:

> The algorithm Ruby uses for compaction is called a two-finger compaction algorithm [.] actually first written about in “The Programming Language LISP: Its Operation and Applications” by Edmund C. Berkeley and Daniel G. Bobrow in 1964.

i.e. in an era where memory was expensive. So I agree:

> It’s quite incredible that this is the algorithm Ruby uses today (57 years later!),

I’m puzzled why, do they target tiny microcontrollers? I thought mostly webserving, and then maybe string processing tilt in their favor over large matrix handling?

---

<div class="post-metadata">

### Author: ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)
#### Post date: [August 9, 2022, 11:25pm UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/17 "2022-08-09T23:25:35Z")

</div>

> In a classic result, Robson showed that all such allocators can  
> suffer from catastrophic memory fragmentation [30]. This  
> increase in memory consumption can be as high as the log  
> of the ratio between the largest and smallest object sizes allo-  
> cated. For example, for an application that allocates 16-byte  
> and 128KB objects, it is possible for it to consume 13× more  
> memory than required.

> [@StefanKarpinski](#):
>
> languages like C, C++ and Rust do not have any way to defragment their heaps either.

Surprisingly, I found MESH that can do that (a drop in replacement, and could apply to Julia too): [https://raw.githubusercontent.com/plasma-umass/Mesh/master/mesh-pldi19-powers.pdf](https://raw.githubusercontent.com/plasma-umass/Mesh/master/mesh-pldi19-powers.pdf)

> **[GitHub - plasma-umass/Mesh: A memory allocator that automatically reduces the...](https://github.com/plasma-umass/Mesh)**
>
> A memory allocator that automatically reduces the memory footprint of C/C++ applications. - GitHub - plasma-umass/Mesh: A memory allocator that automatically reduces the memory footprint of C/C++ a...

> Crucially and counterintuitively, Mesh performs com-  
> paction without relocation; that is, without changing the  
> addresses of objects. This property is vital for compatibility  
> with arbitrary C/C++ applications. To achieve this, Mesh  
> builds on a mechanism which we call _meshing_  
> […]  
> Our analysis shows that Mesh breaks the above-mentioned Robson worst  
> case bounds for fragmentation with high probability [30], as  
> memory reclaimed by meshing is available for use by any  
> size class. This ability to redistribute memory from one size  
> class to another enables Mesh to adapt to changes in an ap-  
> plication’s allocation behavior in a way other segregated-fit  
> allocators cannot.
> 
> We implement Mesh as a library for C/C++ applications  
> running on Linux or Mac OS X. Mesh interposes on memory  
> management operations, making it possible to use it without  
> code changes or recompilation by setting the appropriate  
> environment variable to load the Mesh library (e.g., export  
> LD\_PRELOAD=libmesh.so on Linux). Our evaluation demon-  
> strates that our implementation of Mesh is both fast and  
> efficient in practice. It generally matches the performance of  
> state-of-the-art allocators while guaranteeing the absence of  
> catastrophic fragmentation with high probability. In addition,  
> it occasionally yields substantial space savings: replacing the  
> standard allocator with Mesh automatically reduces memory  
> consumption by 16% (Firefox) to 39% (Redis).  
> […]  
> Mesh enables compaction without relocating object addresses;  
> it depends only on hardware-level virtual memory support,  
> which is standard on most computing platforms like x86 and  
> ARM64. Mesh works by finding pairs of pages and merging  
> them together physically but not virtually: this merging lets  
> it relinquish physical pages to the OS.

Still mimalloc is always fastest (or close to within 3%) of the other allocators benchmarked there, including MESH, which can be up to 155x slower…

---

<div class="post-metadata">

### Author: ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)
#### Post date: [August 10, 2022, 1:40am UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/18 "2022-08-10T01:40:42Z")

</div>

I guess we could run the GCBenchmarks with different mallocs, not sure how easy/hard that would be, but maybe there is some possible benefit there

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [August 10, 2022, 3:06am UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/19 "2022-08-10T03:06:12Z")

</div>

> [@Steven\_Sagaert](#):
>
> julia heap would need more than the specified limit it exits with an OutOfMemory exception. So only julia exits cleanly and you host server never crashes. I’ m sure sysadmins will appreciate that 🙂

systemd-oomd does something like this at a system level. My desktop machine never goes into a multi minute thrash freeze anymore.

---

<div class="post-metadata">

### Author: ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)
#### Post date: [August 10, 2022, 3:15am UTC](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224/20 "2022-08-10T03:15:31Z")

</div>

> [@Palli](#):
>
> but in 64-bit it’s at least close to free

Imagine your heap has say 10MB chunks each of which has 100kB of randomly located integer arrays… Let’s say you’ve got 1000 of these arrays, so you have 100MB allocated, but in 10GB of virtual address… The OS knows nothing about the fact that these chunks are mostly not in use by Julia… Now try to allocate a Gig of space on your 8G machine with a couple gigs of swap… Boom it’s broken.

[Next page](https://discourse.julialang.org/t/julia-gc-heap-fragmentation-out-of-memory-push-append/85224.md?page=2)
