<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Performance on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/performance/</link><description>Recent content in Performance on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Aug 2026 04:16:12 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/performance/index.xml" rel="self" type="application/rss+xml"/><item><title>Stack vs Heap: Memory Allocation Models</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-stack-vs-heap-memory-allocation-models/</link><pubDate>Sun, 02 Aug 2026 04:16:12 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-stack-vs-heap-memory-allocation-models/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;The stack and heap are two distinct memory regions used for different allocation strategies at runtime. The stack manages function call frames automatically via a single pointer increment/decrement, while the heap handles dynamic allocations with flexible lifetimes through an allocator. The distinction directly affects allocation speed, data lifetime, size constraints, and thread safety — core considerations in systems, embedded, and performance-sensitive programming.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360"&gt;&lt;line x1="320" y1="8" x2="320" y2="352" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="160" y="28" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,Menlo,monospace" font-size="17" font-weight="700"&gt;STACK&lt;/text&gt;&lt;text x="160" y="46" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,Menlo,monospace" font-size="10"&gt;grows downward, LIFO&lt;/text&gt;&lt;line x1="52" y1="60" x2="52" y2="300" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="52" y="56" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;high&lt;/text&gt;&lt;text x="52" y="314" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;low&lt;/text&gt;&lt;rect x="76" y="252" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="181" y="276" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: main()&lt;/text&gt;&lt;rect x="76" y="209" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="181" y="233" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: compute(n)&lt;/text&gt;&lt;rect x="76" y="166" width="210" height="38" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="2"/&gt;&lt;text x="181" y="190" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="12"&gt;frame: factorial(3)&lt;/text&gt;&lt;polygon points="290,166 302,160 302,172" style="fill:var(--compare-a)"/&gt;&lt;text x="306" y="172" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;SP&lt;/text&gt;&lt;rect x="76" y="88" width="210" height="70" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="4,3"/&gt;&lt;text x="181" y="127" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="11"&gt;unused&lt;/text&gt;&lt;text x="181" y="326" text-anchor="middle" style="fill:var(--compare-a)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;auto-managed · O(1) · fast&lt;/text&gt;&lt;text x="181" y="341" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;~1-8 MB per thread&lt;/text&gt;&lt;text x="480" y="28" text-anchor="middle" style="fill:var(--primary)" font-family="ui-monospace,monospace" font-size="17" font-weight="700"&gt;HEAP&lt;/text&gt;&lt;text x="480" y="46" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="10"&gt;unordered, explicit lifetime&lt;/text&gt;&lt;rect x="356" y="60" width="248" height="240" rx="6" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="5,3"/&gt;&lt;rect x="372" y="76" width="90" height="42" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="417" y="101" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Object&lt;/text&gt;&lt;rect x="472" y="76" width="80" height="34" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="512" y="97" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Vec&amp;lt;T&amp;gt;&lt;/text&gt;&lt;rect x="372" y="128" width="60" height="30" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="3,2"/&gt;&lt;text x="402" y="147" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;free&lt;/text&gt;&lt;rect x="442" y="120" width="110" height="50" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="497" y="149" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;HashMap&lt;/text&gt;&lt;rect x="372" y="172" width="55" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="399" y="196" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Box&lt;/text&gt;&lt;rect x="437" y="184" width="50" height="28" rx="3" style="fill:none;stroke:var(--border)" stroke-width="1" stroke-dasharray="3,2"/&gt;&lt;text x="462" y="201" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;free&lt;/text&gt;&lt;rect x="372" y="224" width="130" height="46" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="437" y="251" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;String data&lt;/text&gt;&lt;rect x="512" y="228" width="60" height="35" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="542" y="250" text-anchor="middle" style="fill:var(--content)" font-family="ui-monospace,monospace" font-size="11"&gt;Arc&lt;/text&gt;&lt;text x="480" y="326" text-anchor="middle" style="fill:var(--compare-b)" font-family="ui-monospace,monospace" font-size="10" font-weight="600"&gt;manual/GC · flexible · fragments&lt;/text&gt;&lt;text x="480" y="341" text-anchor="middle" style="fill:var(--secondary)" font-family="ui-monospace,monospace" font-size="9"&gt;limited by OS / RAM&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Stack&lt;/th&gt;
&lt;th&gt;Heap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Allocation mechanism&lt;/td&gt;
&lt;td&gt;Pointer decrement — O(1), no bookkeeping&lt;/td&gt;
&lt;td&gt;Allocator call (malloc/new) — higher constant, free-list bookkeeping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deallocation&lt;/td&gt;
&lt;td&gt;Automatic on scope/frame exit&lt;/td&gt;
&lt;td&gt;Explicit (free/delete) or garbage collector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data lifetime&lt;/td&gt;
&lt;td&gt;Bound to the declaring scope or call frame&lt;/td&gt;
&lt;td&gt;Arbitrary; can outlive any function call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size constraint&lt;/td&gt;
&lt;td&gt;Fixed at thread creation (typically 1–8 MB)&lt;/td&gt;
&lt;td&gt;Limited only by available virtual memory / RAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size known at compile time&lt;/td&gt;
&lt;td&gt;Required — compiler must know the type&amp;rsquo;s layout&lt;/td&gt;
&lt;td&gt;Not required — length/capacity decided at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fragmentation&lt;/td&gt;
&lt;td&gt;None — LIFO order keeps allocation contiguous&lt;/td&gt;
&lt;td&gt;Yes — internal and external fragmentation accumulate over time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Thread ownership&lt;/td&gt;
&lt;td&gt;Each thread has its own stack; no synchronization needed&lt;/td&gt;
&lt;td&gt;Shared across threads; allocator must serialize internally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure mode&lt;/td&gt;
&lt;td&gt;Stack overflow → immediate crash (SIGSEGV/signal)&lt;/td&gt;
&lt;td&gt;OOM → null / exception / OOM-killer; potentially recoverable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stack allocation is a single SP register decrement; heap allocation invokes an allocator with metadata updates, free-list traversal, and possible OS syscalls.&lt;/li&gt;
&lt;li&gt;Stack lifetime is strictly scoped to the function frame — data cannot be returned by pointer from the stack safely; heap memory can be returned, stored globally, or transferred across threads.&lt;/li&gt;
&lt;li&gt;Each thread has its own stack and needs no locking; the heap is process-wide and requires allocator-level synchronization on every alloc/free.&lt;/li&gt;
&lt;li&gt;Stack size is fixed and small (set by the OS or linker script); heap can grow dynamically, making it the only viable region for large buffers or runtime-sized collections.&lt;/li&gt;
&lt;li&gt;Heap fragmentation is a real operational concern in long-lived or allocation-heavy processes; the stack never fragments because it always grows and shrinks from one end in LIFO order.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stack&lt;/strong&gt; — Prefer the stack for local variables, function arguments, and fixed-size value types whose lifetime is bounded by the enclosing scope — it is faster, deterministic, and eliminates entire classes of memory bugs.&lt;/p&gt;</description></item></channel></rss>