您似乎正在使用local 模式(一个驱动程序也作为唯一的执行程序),但它也应该适用于其他集群模式。
启用BlockManagerMasterEndpoint 的INFO 日志记录级别,以了解Spark 看到您在命令行中设置的属性(如spark.driver.memory)有多少内存。
log4j.logger.org.apache.spark.storage.BlockManagerMasterEndpoint=INFO
当您启动spark-shell --conf spark.driver.memory=2g 时,您将看到以下内容:
$ ./bin/spark-shell --conf spark.driver.memory=2g
...
17/05/07 15:20:50 INFO BlockManagerMasterEndpoint: Registering block manager 192.168.1.8:57177 with 912.3 MB RAM, BlockManagerId(driver, 192.168.1.8, 57177, None)
如您所见,可用内存为 912.3,计算如下(参见 UnifiedMemoryManager.getMaxMemory):
// local mode with --conf spark.driver.memory=2g
scala> sc.getConf.getSizeAsBytes("spark.driver.memory")
res0: Long = 2147483648
scala> val systemMemory = Runtime.getRuntime.maxMemory
// fixed amount of memory for non-storage, non-execution purposes
val reservedMemory = 300 * 1024 * 1024
// minimum system memory required
val minSystemMemory = (reservedMemory * 1.5).ceil.toLong
val usableMemory = systemMemory - reservedMemory
val memoryFraction = sc.getConf.getDouble("spark.memory.fraction", 0.6)
scala> val maxMemory = (usableMemory * memoryFraction).toLong
maxMemory: Long = 956615884
import org.apache.spark.network.util.JavaUtils
scala> JavaUtils.byteStringAsMb(maxMemory + "b")
res1: Long = 912
让我们回顾一下 Web UI 是如何计算内存的(这与上面的不同,应该只是显示值!)。这是令人惊讶的部分。
Web UI 中存储内存的显示方式由 utils.js 中的自定义 JavaScript 函数 formatBytes 控制,该函数(映射到 Scala)如下所示:
def formatBytes(bytes: Double) = {
val k = 1000
val i = math.floor(math.log(bytes) / math.log(k))
val maxMemoryWebUI = bytes / math.pow(k, i)
f"$maxMemoryWebUI%1.1f"
}
scala> println(formatBytes(maxMemory))
956.6
956.6!这正是 Web UI 显示的内容,并且与 Spark 的 UnifiedMemoryManager 认为可用内存完全不同。 相当令人惊讶,不是吗?
我认为这是一个错误并填写为SPARK-20691。