{"post":{"slug":"allocation-profiling-2026","title":"Allocation Profiling: Finding What Your Code Is Creating","excerpt":"A program with no memory leak can still spend a third of its time in garbage collection. Allocation profiling shows what is being created, which is usually more actionable than what is retained.","category":"code","date":"January 7, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">A</span> service uses a stable amount of memory. There is no leak, memory usage is flat, and the garbage collector runs constantly and consumes a substantial fraction of available CPU.\n\nNothing is being retained. Everything is being *created* — a high rate of short-lived objects that are collected almost immediately. The collector is doing exactly what it should, at a cost that shows up as CPU time nobody attributes to allocation.\n\n## What changed in 2026\n\n- **Continuous allocation profiling in production spread.** Low-overhead sampling made this practical outside development.\n- **Allocation and heap views got clearly separated.** Tooling stopped conflating what is created with what is retained.\n- **Escape analysis improved.** Runtimes eliminating more allocations automatically reduced the need for manual avoidance.\n- **The GC-pressure framing became standard.** Understanding collection cost as a function of allocation rate became common knowledge.\n\n## Two different questions\n\n| | Allocation profiling | Heap profiling |\n| --- | --- | --- |\n| Shows | What is being created | What is currently retained |\n| Finds | GC pressure, avoidable churn | Leaks, unexpected retention |\n| Typical symptom | High CPU in collection | Memory growing over time |\n| Actionable on | Hot paths creating objects | References held too long |\n\nThey answer different questions and are frequently confused.\n\n**Allocation profiling** attributes allocations to the code that made them. Useful when the collector is busy and memory is stable — the objects are being created and discarded rapidly.\n\n**Heap profiling** shows what is alive right now and what holds references to it. Useful when memory grows steadily — something is retaining objects it should release.\n\nA steadily-growing heap is a leak. A high allocation rate with flat memory is churn. Different problems, different fixes.\n\n## Where churn comes from\n\nThe pattern is nearly always allocation inside a loop or a hot path.\n\n**Objects created per iteration.** A temporary object inside a loop running a million times is a million allocations.\n\n**String concatenation in loops.** Each concatenation creates a new string; building incrementally in a loop is quadratic in allocation.\n\n**Boxing and wrapper objects.** Converting primitives to objects in managed runtimes allocates, frequently invisibly.\n\n**Defensive copying.** Copying a collection before returning it is safe and allocates every call.\n\n**Intermediate collections in chained operations.** Each stage of a transformation pipeline may materialise a new collection.\n\n**Closures capturing variables.** In some runtimes, capturing state allocates per call.\n\nThe useful lens is *rate*, not size. A large allocation once is fine. A small allocation a million times is the problem, and it is precisely the one that looks harmless in code review.\n\n## Fixing it selectively\n\nMost allocation is irrelevant. Optimising it everywhere makes code worse for no benefit.\n\nFix allocations that a profiler shows in a hot path, and confirm the improvement with a measurement. The usual techniques: reusing buffers rather than allocating per call, preallocating collections to their known size, avoiding intermediate collections in chains, and using value types where the runtime supports them.\n\nObject pooling is a heavier hammer that reintroduces manual lifetime management, which is the thing garbage collection exists to avoid. Reach for it only where profiling shows a specific allocation dominating and simpler approaches have not worked.\n\nThe complementary view matters too: a CPU flame graph will show time spent in collection, which tells you whether allocation is a problem at all before you go looking for it — see [flame graphs](/blog/flame-graphs-explained-2026).\n\n## Common mistakes\n\n- **Confusing allocation rate with a leak.** Flat memory with high churn is not leaking.\n- **Micro-optimising outside hot paths.** Worse code, no benefit.\n- **Object pooling by default.** Reintroduces manual lifetime management.\n- **Profiling in development only.** Production hot paths differ.\n- **Ignoring the collector's own CPU cost.** It appears as unattributed time.\n- **Not measuring after a change.** Runtimes optimise more than you expect.\n- **Assuming allocation is free because there is no leak.** It costs CPU.\n\n## FAQ\n\n**How do I know if allocation is my problem?**\nCheck what fraction of CPU time goes to garbage collection. If it is meaningful, allocation profiling is worthwhile. If it is small, look elsewhere.\n\n**Does this apply to non-garbage-collected languages?**\nDifferently — allocation still costs, and there is no collector. Profiling allocation there is about avoiding allocator overhead and fragmentation rather than collection pressure.\n\n**Will the runtime optimise my allocations away?**\nSometimes — escape analysis eliminates allocations that do not outlive their scope. It is not guaranteed, and measuring after a change tells you whether the runtime was already handling it.\n\n**Should I tune the garbage collector instead?**\nWorth trying and usually less effective than reducing allocation. Collector tuning changes when the cost is paid; reducing allocation removes it.\n\n## Where to go next\n\nFor CPU profiling generally, read [flame graphs](/blog/flame-graphs-explained-2026). For the concurrency model that affects allocation patterns, [async vs threads](/blog/async-vs-threads-2026) and [thread pools](/blog/thread-pools-explained-2026).","hue":310,"metaTitle":"Allocation Profiling: Finding What Your Code Creates","metaDescription":"How allocation profiling differs from heap profiling, why allocation rate costs CPU without leaking, and where to look for avoidable allocations.","keywords":["allocation profiling","heap profiling","garbage collection pressure","memory leak detection","allocation rate","gc tuning","memory performance","developer tools 2026"],"tldr":["**Allocation rate drives collection frequency** — high churn costs CPU even with no leak.","**Allocation profiling and heap profiling answer different questions** — what is created versus what is retained.","**Look for allocations in loops and hot paths** — a small object created per iteration adds up fast.","**Retained memory growing steadily is a leak** — allocation rate alone is not.","**Skip:** micro-optimising allocations outside hot paths. Most allocation is irrelevant."],"readTime":"4 min read","wordCount":815},"related":[{"slug":"memory-leak-node-2026","title":"Finding Memory Leaks in Node: A Practical Procedure","excerpt":"A leaking process gets slower and then dies. Here is how to confirm a leak, find what is retaining memory, and fix the usual culprits.","category":"code","date":"July 25, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"gc-tuning-jvm-2026","title":"JVM GC Tuning: Start With the Collector, Not the Flags","excerpt":"Most JVM garbage collection tuning is flag cargo-culting. Here is how to pick a collector, what to measure, and why heap size is usually the real lever.","category":"code","date":"July 25, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":150},{"slug":"memory-management-explained-2026","title":"Memory management explained in 2026: stack, heap, and everything between","excerpt":"Manual malloc/free, garbage collection, and Rust-style ownership are three fundamentally different tradeoffs. Here is what every developer needs to know in 2026.","category":"code","date":"March 2, 2026","author":"ByteLedger Team","readTime":"6 min read","hue":313}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"adapter-merging-explained-2026","title":"Adapter Merging: Folding a Fine-Tune Back Into the Model","excerpt":"A trained adapter can stay separate and swappable, or be merged into the base weights for faster inference. You cannot have both, and the choice shapes your serving architecture.","category":"ai","date":"January 7, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":221},"older":{"slug":"best-business-insurance-solopreneurs-2026","title":"Best business insurance for solopreneurs in 2026","excerpt":"2026 ranking of business insurance — general liability, professional liability (E&O), cyber. What solo founders actually need vs marketing fluff.","category":"finance","date":"January 7, 2026","author":"ByteLedger Team","readTime":"2 min read","hue":38}}