Rozpocząłem ostatnio pracę nad nowym projektem związanym z Big Data na mój staż. Moi menedżerowie zalecili rozpoczęcie nauki programowania funkcjonalnego (gorąco polecili Scalę). Miałem skromne doświadczenie w korzystaniu z F #, ale nie widziałem, jak ważne jest stosowanie tego paradygmatu programowania, ponieważ w niektórych przypadkach jest on drogi.
Dean wygłosił interesującą rozmowę na ten temat i podzielił się przemyśleniami na temat tego, dlaczego „Big Data” tutaj: http://www.youtube.com/watch?v=DFAdLCqDbLQ Ale to nie było zbyt wygodne, ponieważ Big Data nie oznacza tylko Hadoop.
Ponieważ BigData jest bardzo niejasną koncepcją. Zapominam o tym na chwilę. Próbowałem wymyślić jeden prosty przykład, aby porównać różne aspekty, kiedy mamy do czynienia z danymi, aby sprawdzić, czy funkcjonalny sposób jest drogi, czy nie. Jeśli programowanie funkcjonalne jest drogie i zajmuje mało pamięci dla małych danych, dlaczego potrzebujemy go dla Big Data?
Daleki od wymyślnych narzędzi, próbowałem zbudować rozwiązanie dla jednego konkretnego i popularnego problemu, stosując trzy podejścia: imperatywny i funkcjonalny (rekurencja, korzystanie ze zbiorów). Porównałem czas i złożoność, aby porównać trzy podejścia.
Użyłem Scali do napisania tych funkcji, ponieważ jest to najlepsze narzędzie do pisania algorytmu przy użyciu trzech paradygmatów
def main(args: Array[String]) {
val start = System.currentTimeMillis()
// Fibonacci_P
val s = Fibonacci_P(400000000)
val end = System.currentTimeMillis()
println("Functional way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s, end - start))
val start2 = System.currentTimeMillis()
// Fibonacci_I
val s2 = Fibonacci_I(40000000 0)
val end2 = System.currentTimeMillis();
println("Imperative way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s2, end2 - start2))
}
Funkcjonalny sposób:
def Fibonacci_P(max: BigInt): BigInt = {
//http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
//lazy val Fibonaccis: Stream[Long] = 0 #:: 1 #:: Fibonaccis.zip(Fibonaccis.tail).map { case (a, b) => a + b }
lazy val fibs: Stream[BigInt] = BigInt(0)#::BigInt(1)#::fibs.zip(fibs.tail).map {
n = > n._1 + n._2
}
// println(fibs.takeWhile(p => p < max).toList)
fibs.takeWhile(p = > p < max).foldLeft(BigInt(0))(_ + _)
}
Sposób rekurencyjny:
def Fibonacci_R(n: Int): BigInt = n match {
case 1 | 2 = > 1
case _ = > Fibonacci_R(n - 1) + Fibonacci_R(n - 2)
}
Tryb rozkazujący:
def Fibonacci_I(max: BigInt): BigInt = {
var first_element: BigInt = 0
var second_element: BigInt = 1
var sum: BigInt = 0
while (second_element < max) {
sum += second_element
second_element = first_element + second_element
first_element = second_element - first_element
}
//Return
sum
}
Zauważyłem, że programowanie funkcjonalne jest ciężkie! zajmuje więcej czasu i zajmuje więcej miejsca w pamięci. Jestem zdezorientowany, ilekroć czytam artykuł lub oglądam rozmowę, mówią, że powinniśmy używać programowania funkcjonalnego w informatyce. To prawda, że jest łatwiej i wydajniej, szczególnie w świecie danych. ale zajmuje więcej czasu i więcej pamięci.
Dlaczego więc musimy korzystać z programowania funkcjonalnego w Big Data? Jakie są najlepsze praktyki korzystania z programowania funkcjonalnego (Scala) dla Big Data?