Spark作业峰值执行内存为0、堆外内存异常的原因咨询
数据文件(CSV)说明
- 磁盘大小:12.1GiB
- 序列化内存大小:1.9 GiB
运行代码
###imports import pyspark from pyspark.sql import SparkSession from pyspark.sql import functions as F from pyspark.sql.window import Window as w from pyspark.sql.functions import udf from pyspark.sql.types import StringType ##start session without off-heap spark = SparkSession.builder.\ config("spark.dynamicAllocation.enabled",False).\ config("spark.executor.cores","2").\ config("spark.executor.instances","1").\ config("spark.executor.memory","500m").\ config("spark.sql.adaptive.enabled", False).\ config("spark.sql.files.maxPartitionBytes","13g").\ getOrCreate() ####read in a 1.9 GiB Serialized CSV df_covid = spark.read.csv("gs://xxxxxxxxxxxx.appspot.com/spark_datasets/covid13g.csv", header=True, inferSchema=False) df_covid.cache() ######check the number of partitions df_covid.rdd.getNumPartitions() #output 2 ###To ensure filters don't get pushed down df_covid = df_covid.withColumn("_catted", F.concat_ws('',*df_covid.columns)) ######Apply filter df_covid = df_covid.filter(F.length(df_covid._catted) > 20) ######count post filter rows df_covid.count()
Spark Web UI Executor标签页截图

疑问
- 为什么峰值执行内存为0?我读取了全部数据,进行了列拼接操作,还对数据应用了过滤,且由于过滤是基于拼接后的列,无法下推至读取阶段。
- 为什么峰值JVM堆外内存不为0?我未配置堆外内存,且它默认是关闭的,为何标签页中会显示堆外JVM内存?
问题解答
关于峰值执行内存为0的原因
Spark的「执行内存」特指用于shuffle、join、排序、聚合这类需要跨分区或大规模数据重组的操作内存区域,你的作业流程完全没触发这类操作:
- 读取数据后直接调用
cache(),数据被存入存储内存(Storage Memory),而非执行内存。 - 列拼接、过滤都是单分区内的逐行转换,直接在缓存的存储内存数据上完成,不需要占用执行内存。
- 最后的
count()只是统计各分区行数,同样无需使用执行内存。
因此整个作业没有用到执行内存,峰值显示为0是正常情况。
关于峰值JVM堆外内存不为0的原因
你没配置的是Spark专属的堆外内存(spark.memory.offHeap.enabled默认关闭),但JVM本身运行就会产生原生堆外内存开销,这些会被UI统计进去:
- JVM的NIO缓冲区(比如文件读写用的DirectByteBuffer)、JNI调用的原生内存、GC辅助内存等,都是进程自身的堆外消耗。
- 读取GS上的文件时,底层存储客户端可能会用堆外内存处理网络IO和临时缓存,这部分也会被算入堆外内存统计。
UI显示的是JVM进程整体的堆外内存使用,而非Spark配置的专用堆外内存,所以即使没开Spark堆外内存,数值也不会为0。
内容的提问来源于stack exchange,提问作者figs_and_nuts
相关产品推荐
相关产品推荐

