为什么Scala没有用C或C ++实现


28

有人知道为什么Scala是用Java和.NET而不是C或C ++实现的吗?大多数语言都是用Cor C ++实现的(例如Erlang,Python,PHP,Ruby,Perl)。除了允许访问Java和.NET库之外,用Java和.NET实现的Scala的优点是什么?

更新

如果用C来实现,Scala不会获得更多好处,因为它可以进行更好的调整而不是依赖JVM?


18
而且,能够使用现有的Java库并与Java代码紧密互操作是一个巨大的好处,而不是小事。
陶Szelei

6
@OP:您说的话似乎很难在JVM(或CLR)上实现一种语言。您提到的C语言中的调优远不及CLR或JVM进行的调优。如果平台有所改进,您的语言会自动免费提供。有了选择,再也没有人可以在good'ol C之上实现他们的语言了。
CHII

8
@Chii,只是承认这一点,Java是仍然慢于C.
约书亚Partogi

19
@ jpartogi,Java不能比C慢或快。它们都是语言,不是种马。在某些特定条件下,由Java编译器编译并由某个JVM执行的某些特定代码比C编译器生成的大致可比的代码要慢。在其他一些情况下,后者会更慢。
SK-logic

4
Scala的运行时环境是一个C ++程序。JVM。
mike30 2013年

Answers:


59

这个问题令人困惑,因为C和C ++是语言,而JVM是虚拟机,而.Net是平台。Scala可以用C或C ++实现,并且可以为虚拟机生成机器代码而不是字节码。

回答提出的问题:

Scala并不是用C或C ++实现的,因为Scala(实际上是它的实现语言)是一种更好的语言。

为什么会更好?好吧,请阅读有关Odersky的Scala语言目标的信息

回答可能的问题:

Scala主要生成JVM字节码,因为它提供了极大的可移植性以及诸如可靠而高效的垃圾收集器,运行时优化以及JVM即时编译之类的功能

让我重复最后一件事:JVM将在其运行的代码中编译为机器代码热点。就像C和C ++编译器一样进行编译。

还有其他虚拟机可用,但是Scala的创建者Odersky已经非常熟悉JVM。他打算使用CLR作为替代方案,但是实现这一目标的努力尚未取得成功。

回答可能/应该提出的问题:

与编译为JVM字节码相比,编译为机器代码没有提供足够的好处。

在C或C ++中产生击败JVM等同物的微基准当然是可能的。的确,用C或C ++进行极端优化的代码将击败用Java或Scala进行极端优化的代码。但是,对于长时间运行的程序而言,差别并不是很大。

请注意,Scala并不是一种特别好的脚本语言,恰恰是因为短期运行的程序的开销太大。

但是,在大多数情况下,开发的速度和维护的简便性比执行的速度更为重要。在这些情况下,人们更加关注编写易于理解和更改的高级代码,那么JVM提供的运行时优化可能会轻易击败C或C ++编译器进行的编译时优化,从而使JVM(和CLR) )实际执行速度更快的目标。

因此,无论问题是关于Scala 编译器是机器代码可执行文件,还是Scala 程序是机器代码,潜在的速度提升都不一定会转化为实际的速度提升。

顺便说一下,

我给你一个反例:Haskell。Haskell生成机器代码,但是,Haskell程序在Debian的枪战中的表现要比Scala的差。有鉴于此,有人可以确定直接编译为机器代码的Scala程序会更快吗?


3
@ mike30 Scala可以在任何JVM上运行,即使它不是用C ++编写的,因此该参数也不成立。而且,在运行时,没有C ++代码,只有机器代码。不过,我不确定这是什么意思。
Daniel C. Sobral

3
真正的重点是:生成机器代码比生成字节代码要复杂得多,并且它需要针对周围的每个OS进行特定的实现,并且需要对CPU和其他体系结构(ARM,x86,x86_64)和高级指令(MMX,SSE)进行调整...)。因此,以这种方式将JVM委托给这方面。
拉斐尔

2
如果您过多地谈论执行性能,那么为什么不谈论内存性能呢?您是否担心事情会出乎您的想象?
luke1985 '16

3
@ lukasz1985它确实可以提高性能,但是性能讨论涵盖了这一点,因此在这方面是无关紧要的。剩下的就是您是否关心应用程序占用了多少内存,然后必须在GC与之之间进行选择,并且我会每次都选择GC,除了非常具体的开发空间外,Scala都不占用这些空间。“不是每个人都有发言权”是胡说八道-每个人都有这个权利。虽然C / C ++由于遗留问题非常重要,但是如果它们在过去五年中发布,它们将永远不会流行。
Daniel C. Sobral

3
@ lukasz1985您唯一不理解的证据是我不同意您的看法。对此的另一种解释是您错了。而且,作为一个活着的人,然后“编程”,我对采用C和C ++替代现代替代方案所涉及的决策有第一手的看法,我提及的目的不是证明我的观点,而是要与您的观点相反:相似性与口头语言毫无关系,而与机器代码相似。
Daniel C. Sobral

31

在向全世界介绍语言时,面临的一大障碍是图书馆的可用性。对此的传统响应是提供基于C的FFI(外部功能接口),以允许您访问基于C的库。由于多种原因,这是不理想的,其中包括:

  • 库与许多高级语言不兼容的交互方式有很多。例如,如果库想要一个指针struct,你怎么没有指针的语言struct小号应对?
  • 不同库和语言的内存模型之间存在严重的交互,这些交互通常无法解决,或者如果可以解决,则很容易出错和发生错误。
  • 许多FFI的胶合代码是不平凡的,并且假定实际上可能不是通用的知识。(信不信由你,不是所有的程序员都是C语言大师,他们既不希望成为也不应该被要求成为!)

对于C ++,情况甚至更糟。从编译器到同一平台上的编译器(!),C ++甚至与C ++不兼容(在二进制级别),更不用说其他语言了。

以JVM为目标解决了许多此类问题,同时使您可以访问绝对庞大的基于Java的库套件。(有多大?只需对Apache Software Foundation的大量入门者进行选择即可。)

  • Java的调用和所有权约定比C的规则更为规范。
  • JVM还为语言和库提供了一个单一的内存模型(包括垃圾回收),以便与它们进行交互。无需跟踪谁拥有什么以及必须在哪里清理的内容。运行时为您完成。
  • 对于大多数基于JVM构建的语言,FFI的粘合代码是不存在的(因为它是作为语言幕后的框架提供的)。无需使用Java进行编程,例如,可以访问Scala,Clojure,JRuby等中的Java库。访问Java对象的方式与访问本机“对象”的方式相同(使用引号引起,因为例如,Clojure不会具有OOP意义上的实际对象)和您的母语。

除了这些优点之外,您还具有其他优点,可以在Java运行的任何地方运行而无需重新编译(但需要进行测试!:编写一次,在任何地方进行测试),并且可以使用Java相当出色的JIT技术。

CLR提供了类似的优势,但是增加了IMO的弱点:它几乎是供应商锁定的环境。(是的,我对Mono有所了解。我仍然认为这是一个供应商锁定环境。)


3
您确实意识到C#和CLR实际上是任何人都可以使用的开放标准。
Erin

7
我认为关于“我知道Mono”然后“仍然认为这是供应商锁定环境”的地方应该给您一些线索,Erin。
正确的意见

3
@Erin并不是所有的.NET Framework都可以
替代

1
@alternative:如果太多的锁定,请考虑一下Java一致性测试仍然不是免费的,对于Java来说,它最多只有六分之一,而其他测试最多只有六分之一。
Deduplicator

18

根据这次采访,访问现有Java基础结构和库是主要原因。

... Java是存在非常严格的约束的现有语言。结果,我无法做很多我想做的事情-我坚信那是做它们的正确方法。因此,在那之后,当我的工作重点基本上是使Java变得更好时,我决定是时候退后一步了。我想从一个干净的表开始,看看是否可以设计出比Java更好的东西。但与此同时,我知道我不能从头开始。我必须连接到现有的基础架构,因为否则,在没有任何库,工具和类似东西的情况下,一无所有地引导自己是不切实际的。

因此,我决定,即使我想设计一种不同于Java的语言,它也始终会连接到Java基础结构— JVM及其库。那是主意...


10

您提到的所有其他语言(Erlang,Python,PHP,Ruby,Perl)都 Java和.NET 之前创建。如果这些语言的创建者当时可以使用Java或.NET运行时环境,那么他们在构建语言时可能会利用它们。

当然,我不能代表这些语言的开发者,所以我不能肯定地说他们在构建它们时会使用.NET和/或Java,但是在我看来,这就像一个好主意。毕竟,通过将语言设计为可编译为Java / .NET字节码,您可以获得JIT编译器/优化器的所有优势,您的语言可自动在Java / .NET所运行的所有平台上运行,您可以访问所有Java / .NET库等。


2
所描述的优点是例如针对JVM(Jython)和.NET(IronPython)重新实现Python的某些原因。
dancek 2011年

2
-1:假设新语言可能已经依赖于特定平台(.Net或JVM),因为它们可以使用对我来说似乎不是一个好主意。例如,我认为Python或Erlang在此类平台上运行没有任何充分的理由。Hystory不能全部说明。
Klaim 2011年

1
甚至PHP也永远无法在JVM或.Net上完成其工作。@Dean Harding>我认为IronPython或Jython并没有证明任何有价值的东西。
Klaim

1
抱歉,我不清楚,我的意思是说它不是“成功”(PHP或Python),因为在JVM或.Net上进行工作意味着很多事情会使许多开发人员恼火,他们比目前更多的利基语言。在技​​术方面,该平台(.Net或JVM)可能会出现问题,因为它确实驱动了您在其上构建语言的方式。用机器进行说明是一种精确制作所需语言的方法。因此,无论有没有可用的JVM,我都看到0个充分的理由来构建.Net和JVM。除了快速实施。
Klaim

2
小修正:Java比PHP老。但是PHP最初是CGI程序,后来变成了Apache httpd模块,因此变得很大。两者(cgi和httpd模块)都不适用于Java。因此,事情并不是那么容易,JVM并不是万能的平台。;-)
johannes

6

C代码被静态编译为本机代码(机器代码)。

Scala被静态编译为Java字节码,然后根据需要动态编译为优化的本机代码。过程:

Scala代码 ---静态编译至-> JVM字节码 --- JVM热点动态编译至-> 本机代码

构建/运行任何语言的常规选项:

  • a)通过运行时解释器引擎直接解释源代码
  • b)将代码静态编译为本地代码(可能通过中间阶段,例如源-> C->本机)
  • c)将源代码静态编译为较低级别的中间代码,并在运行时对其进行解释
  • d)将源代码静态编译为较低级的中间代码,然后使用初始解释,然后使用动态编译和优化技术转换为本地代码。解释代码直到找到典型的执行路径和瓶颈,然后编译代码以在典型条件下最快地执行。当执行条件的变化足以保证此条件时,将对其进行重新编译/重新调整

您的问题:“为什么Java将(d)与JVM一起使用,而不(b)与C中间代码一起使用?”

回答:

首先,观察到Scala的一个比C语言更高级的语言,具有编程能力,易于编程和简洁的特点。由于具有一流的函数和更高阶的函数,隐式函数,作为对象的函数,闭包和循环,支持尾递归编译为快速的堆栈保存循环,所有作为对象,所有运算符作为方法,因此它比Java大约“高1级”可以在库,案例类和归约(模式匹配)中进行(重新)定义,隐式类型派生,通过扩展的多可继承特征和扩展的泛型实现更强的多态性,对和元组和缺点(列表和树)的内置语法)和地图,支持不可变的数据结构,支持功能强大的“反应式”并行和并发计算,并在参与者之间进行消息复制和传递,对任意特定于域的DSL,脚本功能和REPL的高级支持。由于对象定向,指针管理和垃圾回收,字符串支持,多线程支持和并发控制以及标准API库,Java比C大约“高1级”。

  1. 性能:对于高级语言,(d)的性能比(a)-(c)更快。
    直接编写和手动优化的C代码速度很快。但是,静态编译为C的高级语言相对较慢。Java设计师对此非常了解。他们当前的“热点”设计将性能提升了一个数量级。在单核上,Java HotSpot代码的平均速度是“人类优化的C”的“ 50%速度”(最好的情况是“ 120%的速度”,最坏的情况是“ 30%的速度”)。当然,这是将苹果与橙子进行比较-低级代码与高级代码。那将是很多更糟糕的是,如果不使用热点优化。要确认,只需通过JVM args禁用热点编译!或者在热点不存在或不成熟时考虑Java 1和2的性能。或者尝试通过C编译另一种语言-例如perlcc。因此,以上内容对于使用功能强大且富有成效的语言非常有用。随着进一步的发展,JVM有可能(甚至有可能)很快平均超过手工编码的C。Scala的平均速度仅为Java的70-80%。但是scala可以在多个内核上进行强大扩展(尚待进一步改进),而java可以部分实现,而C则不能。此类高级语言的单核性能等级为:

    解释<静态编译<动态编译

    多核性能/可伸缩性的等级为:

    解释后的动态代码<静态编译的命令性代码<静态编译的功能/声明性代码<动态编译的功能/声明性代码

    由于处理器速度已经达到极限,并且根据摩尔定律,现在内核的数量在增加,这使scala成为赢家。Scala在多核上的速度非常快,将来可能会比C或Java快几倍。静态编译为C显然不是最快的选择。

  2. 互操作性:广泛支持的VM上的语言具有比“隔离”语言更好的语言互操作性。Scala只需导入它们并像使用Scala类,特征和对象一样使用它们,即可“自动”使用Java类,接口和对象。对于其他JVM语言(例如Groovy,Clojure,JRuby和JPython),也可以实现类似的操作-易于互操作,这取决于每种语言被编译为可理解和可用的Java运行时类/接口/对象的程度。“免费”(如“接近”)来了很多。Scala通过JNA的继任者JNA与C进行互操作-尽管付出了一些努力,但是随着时间的流逝,这些工具已经得到了很好的简化。JNA实际上可以与任何语言的已编译本机代码进行互操作-但是您必须知道已编译数据类型和函数的确切结构。如果不,

  3. 可移植性:JVM可在多种操作系统平台/版本上“开箱即用”运行。 Scala将自动移植到这些。值得注意的例外是iOS(iPad / iPhone / iPod)-Apple阻止了“商业”而不是“技术”了。在JVM的最初设计期间,这是12年前无法预料的。JVM在许多其他服务器,台式机,移动设备和嵌入式设备上运行良好,包括不支持C的服务器-包括带有Google改编的Dalvik VM的Android(售出的新手机中有50%以上)。当然,C代码可在多种平台上运行,因此可以被评为“在Java之上或可能在Java之上”(特别是C是Objective-C的子集)。但是C将以(1),(2)和(3)为代价。 当然,iOS上的HTML5 / javascript / webkit(或Objective-C)表示层可以与远程scala应用程序进行互操作-因此开发人员应该非常愿意这样做。当然,它们的生产力会降低。

  4. 工具和库:显然,有成千上万的商业和开源Java库和工具可以利用Scala加以利用,而与C相比更多。

  5. 安全性: -在受控的应用程序服务器或JVM环境上运行,可为安全策略和限制提供更强大的支持,这在公司环境中可能非常有价值。


4

JVM / CLR

JVM(和CLR)在优化和代码可移植性方面提供了独特的优势。

据我所知,只有Scala的JVM版本保持最新,而.NET版本却没有。


3

看起来您正在混合两个不相关的内容。

第一个是,Scala作者使用哪种编程语言来实现Scala?

答案是Scala本身。确实,这是唯一可以接受的答案,因为如果您发明了这种新语言,但不要自己使用它来实现它-它有什么用?

第二件事是,运行Scala编写的程序的目标平台是什么?

在这里,选择变得更加有趣,但是就目前而言,唯一可以100%工作的目标是JVM。对.NET的支持仍在进行中。另外,有些人正在努力使Scala编译为javacsript。从理论上讲,没有什么可以阻止某人添加更多的“后端”来编译为C,C ++,LLVM,本机代码或其他任何东西。

为什么选择JVM作为主要平台?我的猜测是因为

  • 每个人都想要垃圾收集
  • 大量好的库可供使用
  • 大量的程序员对Java感到无聊,他们准备跳到新的东西,但仍受JVM的限制(没有人愿意将其现有代码迁移到另一个平台)

我不明白为什么不能用C或C ++实现垃圾收集器?我认为这不是一个很好的理由。Python已经做到了。Ruby已经做到了。哎呀,甚至埃尔朗都做到了。谁知道Scala用C或C ++编写可能会得到更好的垃圾收集器?
2011年

1
我的意思是“真正的”垃圾收集。我认为引发此类问题的垃圾回收不够好。甚至连JVM都不够好-否则像AzulSystems这样的人将无法通过帮助其他人克服JVM的不足来谋生。
artem 2011年

还有图书馆。使用带有垃圾回收语言的显式内存管理编写的库确实很困难。一种迹象表明,Java人特别坚持要把所有东西都放在“纯Java”中。
artem 2011年

0

首先-我想您真正想问的是,为什么Scala并不是严格意义上的编译语言。我会告诉你我不知道。但是我也要告诉你,没有理由偏爱JVM而不是原生代码。

为什么?原因很简单:任何虚拟化技术都占用大量内存,产生不必要的开销和另一层间接。这与它们的实现无关—这实际上是与虚拟化核心概念背后的逻辑有关的问题。不管你做什么,你会总是与差的特性而告终。尤其是JVM占用大量内存。它不再那么慢,因为它拥有自己的运行时编译器在后面运行,但是仍然-它必须运行编译器过程才能发现最拥挤的代码部分并将其转换为二进制代码。

就是说-我认为使Scala基于JVM的唯一原因可能是该语言的普及。我还猜想这种决定的背后有些懒惰,因为在JVM上实现一种语言比弄清楚如何组装成跨平台的工作看起来更容易-甚至使用现有的C后端也需要大量的工作,这是因为事情并没有像JVM那样标准化。

这就是我能想到的原因,但请记住,可能还有其他原因-例如许可问题和其中涉及的政治(这是我永远都不想涉足的肮脏事物)。


-2

尚不清楚是否有更好的调优能力是一个很好的权衡。JVM可以在运行时进行优化,这通常至少足够好,即使不优于静态编译通常会发生的效果。(显然,对于特定的应用程序和工作负载,原则上应该可以通过静态优化击败JIT,但实际上您通常没有确切的工作负载,甚至没有整个应用程序。)


这读起来更像是一个评论,看看如何回答
蚊蚋
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.