# Interesting question about heap allocation vs stack allocation vs garbage collector

**URL:** <https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257>\
**Category:** Help & Support\
**Created:** [January 12, 2022, 4:30pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257 "2022-01-12T16:30:54Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![rkasinsky](https://avatars.discourse-cdn.com/v4/letter/r/bcef8e/32.png) [@rkasinsky](https://forum.crystal-lang.org/u/rkasinsky)\
**Post date:** [January 12, 2022, 4:30pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/1 "2022-01-12T16:30:55Z")

</div>

```auto
def test
  a_on_the_stack : Int32 = 2
  puts a_on_the_stack
end

```

The object `a_on_the_stack` of type `Int32` is allocated on the stack, so there is no GC involved. When the stack is popped, the variable goes away.

If instead I wanted it to go to the heap, I would do:

```auto
def test
  a_on_the_heap = Int32.new(2)
  puts a_on_the_heap
end

```

Because `a_on_the_heap` goes out of scope after the method returns, I assume that the GC would eventually kick in to free the memory allocated on the heap by the variable `a_on_the_heap` above. **Is that correct?**

My question then becomes:

Is there any way in Crystal to free the allocated heap memory **manually** , without having to rely on the GC?

Something like:

```auto
def test
  a_on_the_heap = Int32.new(2)
  puts a_on_the_heap
  free a_on_the_heap # <=========== HERE
end

```

Thanks!

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 12, 2022, 4:39pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/2 "2022-01-12T16:39:36Z")

</div>

> [@rkasinsky](#):
>
> If instead I wanted it to go to the heap, I would do:

I’m pretty sure `2` and `Int32.new(2)` are both on stack as latter is essentially just doing `2.to_i32` and `Int32` is a struct which is a value type.

> [@rkasinsky](#):
>
> Is there any way in Crystal to free the allocated heap memory **manually** , without having to rely on the GC?

You can manually call `GC.collect`. But, as far as I know, there isn’t a way to circumvent that for memory that was originally allocated by the GC? Or if you do, I imagine that would cause some issues if the GC tries to free memory that’s already freed, or maybe it would know that?

[GC.collect doesn't seem to be working. · Issue #11491 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/issues/11491) and [WeakRef doesn't seem to work? · Issue #10469 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/issues/10469) may also be worth a read.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [January 12, 2022, 5:02pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/3 "2022-01-12T17:02:33Z")

</div>

> [@Blacksmoke16](#):
>
> I’m pretty sure `2` and `Int32.new(2)` are both on stack as latter is essentially just doing `2.to_i32` and `Int32` is a struct which is a value type.

Exactly. It seems @rkasinsky might be confused with Java semantics, where `int` is a primitive type and `Integer` is a class type. In Crystal, there is no such distinction. `Int32` is a value type, so it’s located on the stack.

> [@rkasinsky](#):
>
> Is there any way in Crystal to free the allocated heap memory **manually** , without having to rely on the GC?

This was actually just asked on Stack Overflow, see answer there: [How to turn off the GC in Crystal and do memory management yourself, without any GC? - Stack Overflow](https://stackoverflow.com/questions/70674284/how-to-turn-off-the-gc-in-crystal-and-do-memory-management-yourself-without-any)

---

<div class="post-metadata">

**Author:** ![rkasinsky](https://avatars.discourse-cdn.com/v4/letter/r/bcef8e/32.png) [@rkasinsky](https://forum.crystal-lang.org/u/rkasinsky)\
**Post date:** [January 12, 2022, 6:53pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/4 "2022-01-12T18:53:22Z")

</div>

So `Int32` works as a Java primitive, in a sense that it never goes to the heap and because of that it never needs to be garbage collected. And it is also an object, so we get the best of both worlds.

I work with real-time systems, so any GC activity is unaccepted. It would be important for Crystal to allow manual memory management. This is paramount for low-latency and systems programming.

Now I’m trying to cause an out-of-heap-memory error, with the following code:

```auto
class Person
   def initialize(name : String)
      @name = name
   end

   def name
      @name
   end

end

count = 0

while count <= 100000000000
  p = Person.new("a")
  p.name
  count += 1
end

```

And then running it with `-Dgc_none`.

But I get no errors 😕

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [January 12, 2022, 7:21pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/5 "2022-01-12T19:21:22Z")

</div>

> [@rkasinsky](#):
>
> It would be important for Crystal to allow manual memory management. This is paramount for low-latency and systems programming.

Then Crystal is not a good fit for your use case. I suggest using Rust. Maybe also take a look at Zig. And maybe Go could also be useful here, not sure! But Crystal is not built for low-latency systems programming, and there’s no way it will ever be.

> [@rkasinsky](#):
>
> And then running it with `-Dgc_none` .
> 
> But I get no errors 😕

What error were you expecting?

I think `-Ggc_none` is recommended a lot on the internet, but I wish that would stop. That flag only exists to debug memory issues related to the GC. It’s not meant to be used for anything else.

---

<div class="post-metadata">

**Author:** ![rkasinsky](https://avatars.discourse-cdn.com/v4/letter/r/bcef8e/32.png) [@rkasinsky](https://forum.crystal-lang.org/u/rkasinsky)\
**Post date:** [January 12, 2022, 7:30pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/6 "2022-01-12T19:30:53Z")

</div>

> [@asterite](#):
>
> Then Crystal is not a good fit for your use case. I suggest using Rust. Maybe also take a look at Zig. And maybe Go could also be useful here, not sure! But Crystal is not built for low-latency systems programming, and there’s no way it will ever be.

I respectfully hope that you are wrong, and other members of the core team disagree. **Isn’t Crystal supposed to be a very fast language? So why not make it suitable for real-time programming?**

I also think you are overestimating the effort. All you have to do is give an option to turn off the GC. And memory management can be done manually.

This is just an opportunity that Crystal should not miss.

---

<div class="post-metadata">

**Author:** ![RespiteSage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/respitesage/32/793_2.png) [@RespiteSage](https://forum.crystal-lang.org/u/RespiteSage)\
**Post date:** [January 12, 2022, 7:31pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/7 "2022-01-12T19:31:12Z")

</div>

Try this to get what you’re asking for:

```crystal
class Person
  def initialize(name : String)
    @name = name
  end

  def name
    @name
  end
end

count = 0u64

while count <= 100000000000u64
  p = Person.new("a")
  p.name
  count += 1
end

puts p

```

And then run it with `crystal build -Dgc_none program.cr; ./program` (and you can add an optional `--release` after `crystal build`). That should get you the OoM you’re looking for (it’ll just show “Terminated” as output, though, once the OS kills the process).

Your code will overflow your count variable (which is an `Int32`, the default integral primitive in Crystal) before you get an OoM crash (probably), so I changed the count to a `UInt64`. I also added code that actually uses `p`, which helps get around optimizations during compilation which remove unused code (which may only happen if you compile with `--release`).

* * *

I agree with @asterite, though, that Crystal just isn’t a great option for your use case. Maybe someone could rewrite the language to use manual memory management or a borrow checker or something, but that would just be a new language.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [January 12, 2022, 10:04pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/8 "2022-01-12T22:04:17Z")

</div>

> [@asterite](#):
>
> But Crystal is not built for low-latency systems programming, and there’s no way it will ever be.

… until someone builds an alternative standard library with manual memory management 🤷‍♂️

Never say never 😆 There have definitely been some endevours in that direction (example: [https://github.com/ffwff/lilith/tree/master/src/core](https://github.com/ffwff/lilith/tree/master/src/core)).

But honestly, I’d like to stress that the _bare language_ should be very well suite for such tasks. Just the stdlib isn’t. It focuses on usability which is a loss for efficient memory management. And that will certainly never change.

But when you have an alternative stdlib, you can swap it. Maybe that’s not completely original Crystal anymore, but it’s at least in part.  
Besides the standard library, shards are another issue, though.

> [@rkasinsky](#):
>
> Isn’t Crystal supposed to be a very fast language? So why not make it suitable for real-time programming?

Crystal is foremost supposed to be easy to use. Unfortunately, that contradicts with manual memory management, because humans are not good at applying that. Crystal happily trades that extra efficiency for better usability by using automated garbage collection. Which makes it still pretty darn fast, by the way. Despite using a very generic GC library.

> [@rkasinsky](#):
>
> I also think you are overestimating the effort. All you have to do is give an option to turn off the GC. And memory management can be done manually.

I can’t see how that would work. We have an option to turn off the GC. But all code expects it to be there. So how do you solve that?

---

<div class="post-metadata">

**Author:** ![rkasinsky](https://avatars.discourse-cdn.com/v4/letter/r/bcef8e/32.png) [@rkasinsky](https://forum.crystal-lang.org/u/rkasinsky)\
**Post date:** [January 12, 2022, 11:03pm UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/9 "2022-01-12T23:03:31Z")

</div>

> [@straight-shoota](#):
>
> I can’t see how that would work. We have an option to turn off the GC. But all code expects it to be there. So how do you solve that?

Oh, I see now. You are talking about the **stdlib**. What does the stdlib include in Crystal? Java has the exact same problem on its _java.util_ package, which has its collections (lists, hashmaps, sets, iterators, etc). The solution is easy, you simply do not use any of those. There are real-time data structures libraries out there that you can use, which produce zero garbage and do not rely on the GC.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 13, 2022, 3:57am UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/10 "2022-01-13T03:57:11Z")

</div>

> [@rkasinsky](#):
>
> What does the stdlib include in Crystal?

This is defined by the prelude file, which by default is [https://github.com/crystal-lang/crystal/blob/master/src/prelude.cr](https://github.com/crystal-lang/crystal/blob/master/src/prelude.cr). However it’s possible to provide your own, which would be a requirement for a fully manual memory managed stdlib.

---

<div class="post-metadata">

**Author:** ![jgaskins](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jgaskins/32/2449_2.png) [@jgaskins](https://forum.crystal-lang.org/u/jgaskins)\
**Post date:** [January 16, 2022, 4:32am UTC](https://forum.crystal-lang.org/t/interesting-question-about-heap-allocation-vs-stack-allocation-vs-garbage-collector/4257/11 "2022-01-16T04:32:36Z")

</div>

> [@rkasinsky](#):
>
> I work with real-time systems, so any GC activity is unaccepted … This is paramount for low-latency and systems programming.

I’ve heard this quite a bit, but I’m curious about numbers. What sort of latency requirements do you have? How certain are you that Crystal’s GC pushes it above your threshold?
