Производительность Scala: императив по сравнению с функциональным стилем

Я плохо знаком с Scala и просто читал Scala Примером. В главе 2 у автора есть 2 различных версии Quicksort.

Каждый - обязательный стиль:

def sort(xs: Array[Int]) {
    def swap(i: Int, j: Int) {
        val t = xs(i); xs(i) = xs(j); xs(j) = t
    }
    def sort1(l: Int, r: Int) {
        val pivot = xs((l + r) / 2)
        var i = l; var j = r
        while (i <= j) {
            while (xs(i) < pivot) i += 1
            while (xs(j) > pivot) j -= 1
            if (i <= j) {
                swap(i, j)
                i += 1
                j -= 1
            }
        }
        if (l < j) sort1(l, j)
        if (j < r) sort1(i, r)
    }
    sort1(0, xs.length - 1)
}

Каждый - функциональный стиль:

def sort(xs: Array[Int]): Array[Int] = {
  if (xs.length <= 1) xs
  else {
    val pivot = xs(xs.length / 2)
    Array.concat(
      sort(xs filter (pivot >)),
           xs filter (pivot ==),
      sort(xs filter (pivot <)))
  }
}

Очевидным преимуществом, которое функциональный стиль имеет по обязательному стилю, является краткость. Но что относительно производительности? Так как это использует рекурсию, мы платим за потерю производительности точно так же, как мы делаем на других императивных языках как C? Или, причем Scala является гибридным языком, "Scala, путь", (функциональный), предпочтен, таким образом более эффективный.

Примечание: Автор действительно упоминал, что функциональный стиль действительно использует больше памяти.

9
задан sivabudh 25 July 2010 в 05:40
поделиться

1 ответ

Это зависит от ситуации. Если вы посмотрите в исходники Scala, то там часто "под капотом" используется императивный стиль, чтобы быть производительным - но во многих случаях именно эти твики позволяют вам писать производительный функциональный код. Поэтому обычно вы можете придумать функциональное решение, которое будет достаточно быстрым, но вы должны быть осторожны и знать, что вы делаете (особенно в отношении структур данных). Например, конкат массива во втором примере не очень хорош, но, вероятно, не так уж плох - но использование здесь списков и их конкат с ::: было бы излишеством.

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

Я бы посоветовал начать с функционального стиля. Если он слишком медленный, переделайте его. Обычно есть лучшее функциональное решение. Если нет, то в крайнем случае можно использовать императивный стиль (или смесь обоих).

11
ответ дан 3 November 2019 в 00:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: