Skip to content

Allow heap allocations in interrupts #2871

Open
@aykevl

Description

@aykevl

Currently, the GC does not allow heap allocations in interrupts. This is not yet enforced (see #1460) but I want to do that eventually. The reason it's not allowed is that there is no synchronisation with the main heap. This can cause issues in various ways:

  • A non-interrupt goroutine might trigger a GC cycle, and meanwhile an interrupt might try to allocate (which could also start a GC cycle, leading to data corruption)
  • An interrupt might trigger a GC cycle, which takes a long time to complete.
  • A non-interrupt goroutine and an interrupt might try to allocate memory, and allocate the same area of memory.

I have looked into the possibility of a GC that can allow heap allocations in interrupts. And while it's technically possible, it is very hard to get right. There is a paper written about this topic, you can read it here.

Some considerations:

  • Many advanced algorithms rely on a fully precise heap, that is, we need to know exactly where pointers are on the stack, heap, and in the .data section. This requires large changes to the compiler and is not compatible with CGo.
  • Memory fragmentation is a problem. We're not currently hitting this very hard, but it's always a risk. According to the paper, the only real solution is compacting the heap, which needs a fully precise heap.

Some options:

  • Disable interrupts during heap allocation. This would work and is easy to implement, but would mean that interrupts are disabled for the duration that GC takes place. This seems like a bad idea to me: interrupts should be able to fire anytime. It would essentially look like running the GC in an interrupt, which is not what you want.
  • Reference counting (which is also a valid GC strategy!) does not suffer as much from pauses as a tracing GC so can be used instead. However, it can still suffer from pauses when a large data structure is deallocated and it has the usual problem of not collecting cyclical references. Also, reference counting can be slow (but this needs to be measured!).
  • It is possible to use a semispace GC (in which the heap area is split in two areas, only one of which is live at any time). GC work can then happen incrementally. The cost would of course be high in RAM consumption and generally this system is very complex and incompatible with CGo.

I believe that at the moment, simply disallowing heap allocations in interrupts is the most reasonable option. However, we might want to investigate one of these solutions in the future. I've made this issue so that we can keep track of the discussion and link to it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions