Spark の Web UI は Job や Executor をモニタリングするためのツール。
aws-glue-samplesから maven:3.6-amazoncorretto-8 ベースでSparkを動かすDockerfileを持ってきて、 History Serverを起動する。Glue で出力された EventLog のパスと認証情報を渡している。
$ git clone https://github.com/aws-samples/aws-glue-samples.git
$ cd aws-glue-samples/utilities/Spark_UI/glue-3_0/
$ docker build -t glue/sparkui:latest .
$ docker run -it -e SPARK_HISTORY_OPTS="$SPARK_HISTORY_OPTS -Dspark.history.fs.logDirectory=s3a://path_to_eventlog
-Dspark.hadoop.fs.s3a.access.key=$AWS_ACCESS_KEY_ID -Dspark.hadoop.fs.s3a.secret.key=$AWS_SECRET_ACCESS_KEY"
-p 18080:18080 glue/sparkui:latest "/opt/spark/bin/spark-class org.apache.spark.deploy.history.HistoryServer"
これで http://localhost:18080 にアクセスし Application を選択すると Job 実行や Executor 追加のタイムラインが表示される。
各 Job をクリックすると次のように Stage と DAG (Directed Acyclic Graph) が表示される。 WholeStageCodeGen は高速化のため処理ごとではなく Stage 単位で Code Generation する処理。 ただ生成されるコードが大きいと JVM の JIT コンパイラがネイティブコンパイルせず interpreter で実行するのでかえって遅くなることもあるそうだ。
Stage の数はコストが大きいシャッフルを必要とする数なので少ない方が良い。 Join のためにかさんでいるのであれば、パラメータを調整するなどしてシャッフルしない Broadcast Hash Join にできないか検討する。
Apache SparkのRDD, DataFrame, DataSetとAction, Transformation - sambaiz-net
さらに Stage をクリックすると各 Executor ごとの Task のタイムラインが表示される。 ほとんどの時間を Computing Time に割けていて、Task の実行時間や Executor への Input Records の統計も概ね均一で、うまく分散できているように見える。
SQL のタブを見ると Optimizer によって最適化されたクエリの Logical plan や、 実際に実行される Physical plan、そのどこにどれくらい時間がかかっているかを確認できる。
参考
Apache Sparkコミッターが教える、Spark SQLの詳しい仕組みとパフォーマンスチューニング Part2 - ログミーTech