# Measure allocation and retained memory

> Distinguish allocation rate, live data, native memory, and thread-local counters when investigating performance.

Canonical: https://alice-lang.org/documentation/advanced/profiling/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

## Ask a precise question

Memory can mean newly allocated bytes, currently reachable objects, GC heap size, process resident memory, or native allocations. These measurements answer different questions. A small live heap can coexist with a high allocation rate; a stable managed heap can coexist with growing native memory.

| Symptom                                       | Start by investigating                                  |
| --------------------------------------------- | ------------------------------------------------------- |
| Frequent short pauses under load              | Allocation rate and GC activity                         |
| Memory grows after each request               | Retained references, caches, subscriptions, queued work |
| Large process memory with modest managed heap | Native resources, mappings, runtime reservations        |
| One loop allocates unexpectedly               | Materialization, closures, boxing, string creation      |
| Performance drops with many workers           | Per-worker buffers, contention, queue growth            |

## A thread-local allocation probe

`GC.GetAllocatedBytesForCurrentThread()` is a cumulative managed-allocation counter for the current thread. Subtract two readings around a synchronous region to estimate that region's allocation. It does not count worker-thread allocations, native allocations, or only the objects still alive. See the [API contract](https://learn.microsoft.com/en-us/dotnet/api/system.gc.getallocatedbytesforcurrentthread?view=net-10.0).

```alice
before = GC.GetAllocatedBytesForCurrentThread()
values = Array(Int32).new(1000)
values[0] = 42
after = GC.GetAllocatedBytesForCurrentThread()
puts after - before
puts values[0]
```

Do not promise a fixed byte count from this example. Object headers, runtime state, and surrounding work matter. Keep console output outside the measured region. Warm up the operation first when assessing steady-state code.

## Avoid misleading measurements

A pipeline may parallelize, so a current-thread delta can miss most allocations. An async continuation may resume on a different thread, making the subtraction unsuitable. JIT warm-up, package startup, file reads, and test infrastructure can dominate a short measurement.

Measure the layer you care about. A zero-allocation kernel test does not imply the CLI, request handler, or whole application allocates zero bytes.

## Reduce allocation with evidence

Use fused iterator sinks, reuse buffers when ownership is clear, avoid materializing intermediate arrays, and use `StringBuilder` for repeated text growth. Compare a baseline and the revised implementation with identical input and output.

If the problem is retention, reducing temporary allocations may not solve it. Find the owner keeping references reachable. Bound caches, unregister events, drain queues, and end task lifetimes deliberately.

## GC configuration

Alice SDK projects default to server and concurrent GC. Those defaults are overridable MSBuild settings, not a universal best choice for every small CLI or constrained host. Measure startup, throughput, and working set under the target workload before changing them.

Calling `GC.Collect()` repeatedly is not a general memory fix. Prefer understanding why data remains reachable or why allocations are excessive. For runtime concepts, use [.NET's GC overview](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals).

For a repeatable optimization investigation, record Alice/.NET versions, build mode, CPU, input, warm-up, iteration count, allocations, result/checksum, and the measurement's thread/process scope.

## Continue reading

- Previous: [Spans, buffers, and pooling](https://alice-lang.org/documentation/advanced/buffers.md)
- Next: [Write secure Alice applications](https://alice-lang.org/documentation/advanced/security.md)
