How OCaml Locals Use a Separate Stack

A list example shows how region-scoped local values can avoid repeated garbage-collected allocations.

Chaîne
Jane Street
Publié
29 févr. 2024
Vidéo
11:07
Lecture
2 min
Diapositives
3
Original
anglais
Ouvrir sur YouTube
En faisant défiler, la vidéo se réduit en bas à droite et continue. Les sous-titres suivent votre langue de lecture.
Langue de lectureDisponible en 2 langues
Cet article n’est pas encore disponible en français ; il s’affiche dans l’original en anglais.
RÉSUMÉ

En 30 secondes

In this OCaml Unboxed episode, the speaker compares heap allocation and garbage collection with allocation on a separate local stack. The loop example shows how non-escaping values can be reclaimed at the end of a region, and why local values may need to survive a function return.

  1. 1Repeated heap allocationEach iteration builds a new list, leaving the previous list unreachable once the reference changes.
  2. 2The cost of collectionThe simplified mark-and-sweep example illustrates the work and potential pauses involved in reclaiming heap objects.
  3. 3Regions bound lifetimesLocal values allocated inside the loop body cannot escape that region.
  4. 4Why a separate stackAn exclave can allow values to survive a function return while remaining within the enclosing region.

À retenir

  1. The example allocates repeated lists on the heap when it does not use locals.
  2. Garbage collection reclaims unreachable values but can add work and latency.
  3. A loop body forms a region whose local values cannot escape.
  4. Ending the region permits its local allocations to be reclaimed together and reused.
  5. The local stack is separate from the call stack because some local values outlive the function that allocated them.
TEXTE INTÉGRAL

Lire le texte remanié, chapitre par chapitre

Transcription seule
01

A list-allocation example

The speaker revisits a program whose local annotations reduce garbage-collected allocation. The example repeatedly constructs and processes a list.

In this installment of OCaml Unboxed, I continue exploring the local mode that my Jane Street colleagues and I are developing in an open-source compiler branch. A previous example reduced garbage-collected allocations using local annotations. Here I want to show where the memory goes and why that works.

The example’s main function, doit, loops with an iteration variable and a list. It calls init to construct the list and then counts multiples of five. First, imagine the program without local annotations and follow the allocations on the heap.

02

Heap allocation and garbage collection

Without locals, old lists become unreachable and are reclaimed by garbage collection. The speaker explains the cost in a simplified mark-and-sweep model.

init constructs a linked list of cons cells on the heap. The list variable points to its beginning. In the next iteration init constructs another list, and list changes to point to the new one. The old cells are no longer reachable through that variable.

When garbage collection runs, the simplified picture is to trace from roots such as stack variables, mark reachable heap objects and reclaim objects that cannot be reached. The current list remains live; the old list can be collected, making space for later allocations.

Tracing reachable heap cells
DIAPOSITIVE 1 / 3Tracing reachable heap cellsThe drawing shows the call-stack reference and the reachable and unreachable list cells.

Garbage collection is valuable: it supports immutable functional programming and makes programs easier to reason about and develop. But finding live data and reclaiming the rest takes work. In the mark-and-sweep picture, collection can pause program execution and touch memory that may displace more useful cached data.

Most programs at Jane Street are fine with garbage collection. For latency-sensitive cases, however, we want to avoid those pauses and other slowdowns. That performance goal motivated our investigation of locals.

03

A separate local stack

Local allocations are confined to regions and can be reclaimed together at a region’s end. A separate stack permits values to survive a function return without escaping their region.

Now consider the local version. The call stack still holds doit and its variables, but init allocates the list cells in a separate area I call the local stack. This is neither the ordinary call stack nor the garbage-collected heap.

init finishes and returns the locally allocated list, which doit can use to count multiples of five. The loop body is a region: local values allocated in that region cannot escape it. When the iteration ends, the analysis guarantees that those allocations are no longer needed.

The separate local stack
DIAPOSITIVE 2 / 3The separate local stackList cells are allocated separately from the call stack and heap.

The runtime can reclaim the region’s local allocations together and reuse the same memory in the next iteration. The deallocation can be as simple as changing the pointer used for the next allocation. It avoids the mark-and-sweep work described in the heap example.

Reclaiming a region
DIAPOSITIVE 3 / 3Reclaiming a regionThe sketch shows the old local allocations being discarded at the end of an iteration.

The separate local stack matters because init can return before its caller finishes using the list. Values created inside an exclave can survive a function return while still being limited to their enclosing region. Function frames and regions do not always have identical lifetimes, so the local allocations cannot simply live in init’s call-stack frame.

Sur la même chaîne

6 diapositives15:33EN
JSJane Street· 26 oct. 2026Figgie Strategy: Reading Hands, Winning Majorities and Pricing CardsBradley, Mike · Jane StreetJane Street traders Bradley and Mike analyze three games to show how private information, market competition and timing affect card prices.Decision MakingMathematicsFintech
1:48:29EN
JSJane Street· 16 oct. 2026How AI Is Changing Programming: John Krazit and Ron MinskyRon Minsky, John Krazit · Jane StreetJane Street’s AI tooling lead and the Signals and Threads host examine agent infrastructure, security, code review and the changing experience of writing software.Agents de codeDeveloper productivityÉvaluations+2
1:36:37EN
JSJane Street· 23 sept. 2026Aaron Bauer on Teaching Software Engineering in the Age of AIRon Minsky, Aaron Bauer · Jane StreetHow learning goals, active practice and editor design shape engineering education when models can generate the code.AI in EducationSoftware engineeringEducation+2
9 diapositives1:05:45EN
JSJane Street· 11 sept. 2026Cyrus Omar on Live Programming and a Computational Commons for Humans and AICyrus OmarA demonstration of Hazel shows how immediate feedback, structured collaboration and carefully scoped permissions could support people and AI agents working together.Programming LanguagesHuman-AI CollaborationWorkflows de développement et tests+2
1:25:00EN
JSJane Street· 2 sept. 2026Eric Mannes on Turning Messy External Data Into Trading ResearchRon, Eric Mannes · Jane StreetFrom commodity futures and an Excel risk system to point-in-time datasets and AI, Eric Mannes explains the domain knowledge behind data engineering at Jane Street.Data quality & curationWorkflows de développement et testsInvesting+2
7 diapositives1:16:29EN
JSJane Street· 26 août 2026Grant Sanderson and Alok Puranik: Positional Encodings Through Group TheoryGrant Sanderson, Alok Puranik · 3Blue1BrownStarting with assumptions about attention, they derive matrix exponentials and connect rotations, decay and Jordan blocks to RoPE and ALiBi.Transformers & attentionMathematicsFondamentaux du ML+1