Spark Executor Memory Architecture
Simple, intuitive breakdown of JVM Executor Memory structure: Reserved, User, Storage, Execution, and Off-Heap memory regions with configuration rules.
Below is the visual structure of a single PySpark Executor JVM process. Spark automatically divides JVM memory into 4 primary regions managed by the Unified Memory Manager.
Hardcoded Spark internal tasks & stability.
Shuffles, Joins, Sorts, Aggregations.
Cached DataFrames (`df.cache()`) & Broadcasts.
Python UDFs, custom HashMaps, Metadata, and non-Spark data structures.
Hardcoded system RAM reserved exclusively for Spark internal engine tasks and system stability.
Used In: System Overhead, Spark Internal Engine
Fixed Constant = 300 MBIf Executor RAM = 1024 MB:
Usable RAM = 1024 MB - 300 MB = 724 MBReserved: 300 MB (Static)Shared dynamic memory pool used for Execution (Shuffles, Joins, Sorts) and Storage (Cached DataFrames, Broadcast Variables).
Used In: Shuffle Buffers, DataFrame Caching, Broadcast Lookups
spark.memory.fraction = 0.6 (Default 60%)Spark Memory = (Total_Heap - 300MB) * 0.6Dynamic shared region for Execution & StorageUsed for intermediate data processing during Shuffles, Joins, Aggregations, Groupings, and Sorting operations.
Used In: SortMergeJoin, HashJoin, GroupBy Aggregations, Window Functions
spark.memory.fraction * (1 - spark.memory.storageFraction)# During a 50GB Sort-Merge Join:
Execution Memory buffers intermediate partition buckets before writing to shuffle disk.Short-lived intermediate join/sort buffersStores cached DataFrames (`df.cache()`), persisted RDDs, and broadcast variables across executor nodes.
Used In: DataFrame Caching, RDD Persistence, Broadcast Variables
spark.memory.storageFraction = 0.5 (Default 50% of Spark Memory)df.cache() # Stores serialized or un-serialized partition blocks in Storage MemoryCached DataFrame Blocks & Broadcast HandlesStores user-defined data structures, custom Python dictionaries, UDF objects, RDD transformations (`map`, `flatMap`), and metadata.
Used In: Python UDFs, Custom Aggregators, Metadata, Internal RDD Maps
User Memory = (Usable RAM) * (1 - spark.memory.fraction)# Custom Python UDF creating large dict:
my_dict = {i: str(i) for i in range(1000000)} # Resides in User MemoryPython/Java Objects & Custom Hash MapsAllocates native C-style memory outside the JVM Heap to completely eliminate Java Garbage Collection (GC) pauses.
Used In: Ultra Large Scale Clusters, Garbage Collection Elimination
spark.memory.offHeap.enabled = true
spark.memory.offHeap.size = 10g--conf spark.memory.offHeap.enabled=true --conf spark.memory.offHeap.size=8gDirect native memory used for Tungsten binary rows