Параметр метода запускает сериализацию в Spark? - PullRequest
0 голосов
/ 21 декабря 2018

Я прочитал руководство по программированию Spark о передаче функций и удивляюсь, что происходит, когда функция ссылается на внешний параметр метода / локальную переменную.

Например, у меня есть этот объект

object Main {
  def main(args: Array[String]): Unit = {
    val ds: Dataset[String] = ???
    ds.map(_ + args(0))
  }
}

Должна ли Spark сериализовать Main?Что если args является локальной переменной внутри main?

1 Ответ

0 голосов
/ 21 декабря 2018

Нет, в обоих этих случаях Spark не сериализует объект Main.Аргументы метода и локальные переменные (которые с точки зрения семантики в значительной степени совпадают) не «принадлежат» окружающему объекту или классу, они связаны с конкретным вызовом метода и поэтому могут быть непосредственно захвачены замыканием.

Как правило, если вам нужна ссылка на некоторый объект для доступа к какому-либо значению, эта ссылка будет захвачена и, следовательно, сериализована:

class Application(n: Int) {
  val x = "internal state " + n

  def doSomething(ds: Dataset[String], param: String): Unit = {
    ds.map(_ + x + param)
  }
}

Обратите внимание, что здесьдля доступа к x, который является экземпляром члена, вам обязательно нужно иметь включающий экземпляр, чтобы он был доступен, потому что это зависит от фактических параметров, с которыми был создан экземпляр.Другой способ увидеть это - помнить, что когда вы используете x в приведенном выше примере, это на самом деле ярлык для this.x:

ds.map(_ + this.x + param)

По сравнению с этим значение param не имееттакая зависимость - она ​​передается как есть методу, и для ее использования нет необходимости обращаться к какому-либо другому включающему объекту.Следовательно, param будет записан и сериализован напрямую.

Вот почему советуют помещать элементы экземпляра в локальные переменные, чтобы не захватывать весь объект: когда вы помещаете значение в локальную переменную,он больше не требует доступа к включающему экземпляру:

val localX = this.x
ds.map(_ + localX + param)

Конечно, если у вас есть ссылки на включающий экземпляр внутри объекта, который вы хотите захватить, как здесь:

class Inner(app: Application)

class Application {
  val x = new Inner(this)

  def doSomething(ds: Dataset[String]): Unit = {
    val localX = x
    ds.map(_ + localX.toString)
  }
}

тогда сохранение его в локальной переменной не помогло бы, потому что Spark все равно нужно было бы сериализовать поле app класса Inner, которое указывает на экземпляр Application.Вот почему вы должны быть осторожны, если у вас есть сложные графы объектов, которые вы используете в методах Spark, которые будут отправлены исполнителям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...