Hone logo
Hone
Problems

Implementing Incremental Garbage Collection Simulation in Go

Simulating incremental garbage collection (GC) is a valuable exercise for understanding how modern GC systems work. This challenge asks you to build a simplified simulation of an incremental GC in Go, focusing on marking and sweeping phases. The goal is to demonstrate the core concepts of incremental collection without the complexities of a full-fledged GC implementation.

Problem Description

You are tasked with creating a Go program that simulates a basic incremental garbage collector. The program should manage a set of objects, track their references, and periodically perform a marking and sweeping phase. The simulation should allow for the creation of objects, the establishment of references between them, and the triggering of a GC cycle. The GC cycle should involve a marking phase (identifying reachable objects) and a sweeping phase (reclaiming memory occupied by unreachable objects). The simulation should provide a mechanism to observe the state of the heap before and after the GC cycle.

Key Requirements:

  • Object Representation: Define a struct Object with a unique ID and a slice of IDs representing references to other objects.
  • Heap Management: Implement a data structure (e.g., a slice or map) to represent the heap, storing the Object instances.
  • Object Creation: Provide a function to create new objects and add them to the heap.
  • Reference Establishment: Provide a function to establish references between objects in the heap.
  • Marking Phase: Implement a marking phase that starts from a set of root objects (e.g., global variables) and recursively traverses the reference graph to mark all reachable objects. Use a simple marking strategy (e.g., a boolean flag on each object).
  • Sweeping Phase: Implement a sweeping phase that iterates through the heap and reclaims memory occupied by unmarked objects. This can be simulated by removing the object from the heap.
  • GC Triggering: Provide a function to trigger the GC cycle (marking and sweeping).
  • Heap Observation: Provide a function to print the current state of the heap (object IDs and references) before and after the GC cycle.

Expected Behavior:

The program should:

  1. Allow the user to create objects and establish references between them.
  2. When the GC is triggered, it should correctly identify and reclaim unreachable objects.
  3. The heap observation function should accurately reflect the state of the heap before and after the GC.

Edge Cases to Consider:

  • Circular References: The marking phase should correctly handle circular references (e.g., object A references object B, and object B references object A).
  • Root Objects: The marking phase should start from a defined set of root objects.
  • Empty Heap: The GC should handle the case where the heap is empty.
  • No Unreachable Objects: The GC should handle the case where there are no unreachable objects.

Examples

Example 1:

Input:
  - Create objects: 1, 2, 3, 4
  - Establish references: 1 -> 2, 2 -> 3, 3 -> 1, 4 -> 1
  - Trigger GC
Output:
  - Heap before GC: [1: [2], 2: [3], 3: [1], 4: [1]]
  - Heap after GC: [1: [2], 2: [3], 3: [1], 4: [1]] (No objects are unreachable)
Explanation: All objects are reachable from root object 4.

Example 2:

Input:
  - Create objects: 1, 2, 3, 4
  - Establish references: 1 -> 2, 2 -> 3
  - Trigger GC
Output:
  - Heap before GC: [1: [2], 2: [3], 3: [], 4: []]
  - Heap after GC: [1: [2], 2: [3], 3: []] (Object 4 is unreachable and removed)
Explanation: Object 4 is not reachable from any root object and is therefore collected.

Example 3: (Circular Reference)

Input:
  - Create objects: 1, 2
  - Establish references: 1 -> 2, 2 -> 1
  - Trigger GC
Output:
  - Heap before GC: [1: [2], 2: [1]]
  - Heap after GC: [1: [2], 2: [1]] (No objects are unreachable)
Explanation: Objects 1 and 2 form a circular reference and are both reachable.

Constraints

  • The number of objects created should not exceed 100.
  • The object IDs should be unique integers.
  • The marking phase should be implemented using a simple depth-first search (DFS) approach.
  • The sweeping phase should iterate through the heap in a linear fashion.
  • The program should be reasonably efficient for the given constraints. Avoid excessive memory allocation or complex data structures.

Notes

  • This is a simulation, so you don't need to implement a real memory allocator. Focus on the logic of marking and sweeping.
  • Consider using a map[int]*Object to represent the heap for efficient object lookup.
  • The root objects can be hardcoded for simplicity.
  • The goal is to demonstrate the core concepts of incremental GC, not to create a production-ready GC implementation.
  • Think about how to represent "marked" objects. A simple boolean flag on the Object struct is sufficient.
  • Error handling is not required for this challenge. Focus on the core GC logic.
Loading editor...
go