与 Java 或其他非函数式语言相比,Scala 究竟如何利用更多的内核?

How exactly does Scala leverage more cores as opposed to Java or other non-functional languages?

我最近在听 Martin Odersky 的视频,他试图解释函数式语言(例如 Scala,但当然不一定 Scala)相对于 OOP 或程序语言。

换句话说,他解释说 Moore's Law 最近让我们失望了,所以要制造处理器 "faster",而不是能够将 t运行 中的晶体管数量加倍核心,CPU 制造商只是提供更多的核心。这反过来又使 CPU 可以被 concurrent/multi-threaded 应用程序更充分地利用。因此,主要的收获是:应用程序的并发性越高,其代码片段越多 运行 同时在不同的内核上,并且 CPU 上的内核越多,程序的整体执行速度就越快。

到目前为止,还不错。

他没能解释(或者更可能是我没能理解)的是为什么 像 Scala 这样的函数式语言比其他非函数式语言更适合并发。由于我们恰好在谈论 JVM space,让我们快速比较一下 Java 和 Scala。如果 Scala 程序是用纯 Java 实现的,那么 parallelize/make 并发变得更加困难, 特别是如果它全部编译为 JVM 字节码并且运行 在具有相同本机功能的相同 JVM 上??

意味着我有两个 JVM 应用程序,用 Java 编写的 App1 和用 Scala 编写的 App2。他们都执行完全相同的任务并完成相同的事情。两者都被编译成 JVM 字节码,并且在安装了相同 JVM 的同一台计算机上 运行。 Scala 应用程序如何能够 "tap into" JVM 功能使其比 Java 更适合并发(因此,在具有更多内核的 CPU 上速度更快)?

当您说您的两个应用程序最终都归结为 JVM 上的字节代码时,您完全正确。大多数可用于 Scala 并发的库和框架也可用于 Java。然而,让 Scala 与众不同的是 Scala 的内置 对不变性的支持。 Scala 拥有非常丰富的不可变集合,这种拥抱不可变性的特性使得为并发和并行应用程序编写代码变得更加容易。 Scala 将用户从编写线程级代码中抽象出来,让用户更专注于业务逻辑。期货 API 在此期间非常方便。

Scala 包含函数式编程范例(即组合函数)并在 actor 中隔离可变状态,通过它您可以消除所有您会 运行 遇到的典型并发问题,例如Java 中的编程线程。这就是为什么选择 Scala 作为设计 Spark 的语言。

现在进入您的问题的主要部分,即与其他非函数式语言相比,scala 如何利用更多的内核:- scala 中的 Futures API 有一个底层执行上下文,它不过是一个可由开发人员配置的线程池。使用此 API 您将能够利用所有核心。

我想对已经提到的内容进行补充。我相信,一般来说,Java 应用程序比 Scala 应用程序更快但可以忽略不计。然而,仅有快速的执行速度是不够的。例如,

我们可以比 Java 更快地开发 Scala 应用程序吗?关键是,即使 Scala 应用程序在执行速度方面慢了 10~15%(例如),但使用 FP 最佳实践开发时间快了~30%,那么使用 Scala(或其他函数式语言)是值得的). FP 强调很多函数的可组合性和类型安全。 FP 的另一个特点是在变量上使用值(不可变变量)。不变性使多核编程更易于管理且不易出错。 Java 可以使用一些 FP 最佳实践来做同样的事情。所以,在开发过程中,Java 程序员会遇到很多不便,因为这些做法在 Java 中并不容易获得。

编译 Java 源代码比 Scala 快吗?好吧,这是一个很大的肯定。 Scala 编译器会检查很多东西,例如implicit 个函数,在编译期间。但是,Scala 程序员编写的单元测试较少,因为编译器会检查函数参数和 return 类型的有效性。如果类型未正确对齐,编译器将中断。

Java 和 Scala 应用程序都被编译成 JVM 字节码并在同一 JVM 下执行,因此,它们应该具有相同功能的论点是错误的。这两个应用程序都受到 JVM 功能的限制,除非其中一个应用程序使用未记录的 JVM 功能。然后,该语言具有 "unfair" 优势。撇开这一点不谈,在相同的 JVM 运行时环境下,一种语言比另一种语言更快的唯一方法是更有效地安排字节码。