v2ex 有用Scala做web开发的吗?

2012-03-20 16:04:37 +08:00
 skywinger
v2ex 有用Scala做web开发的吗?
个人目前正在研究play framework
感觉编译型语言更适合自己。
14992 次点击
所在节点    Scala
90 条回复
iwinux
2012-03-21 11:22:49 +08:00
@skywinger @bhuztez 这楼彻底歪了...

关于 JVM 的 startup time,可以参考 http://en.wikipedia.org/wiki/Java_performance#Startup%5Ftime

虽说不是所有 VM 中最慢的,但也快不到哪里去(这里不讨论运行性能的问题)
bhuztez
2012-03-21 11:25:47 +08:00
@skywinger

--------------------------------------------------------------
class Hello {
public static void main(String argv[]) {
System.out.println("Hello, world!");
}
}
--------------------------------------------------------------

--------------------------------------------------------------
#!/usr/bin/env python2

class Hello(object):

@staticmethod
def main(argv):
print "Hello, world!"


if __name__ == "__main__":
import sys
Hello.main(sys.argv[1:])
--------------------------------------------------------------

$ javac Hello.java
$ time java -cp . Hello
Hello, world!

real 0m0.075s
user 0m0.050s
sys 0m0.021s

$ time python hello.py
Hello, world!

real 0m0.039s
user 0m0.029s
sys 0m0.009s

$ time pypy hello.py
Hello, world!

real 0m0.047s
user 0m0.031s
sys 0m0.014s

要注意为了尽可能体现JVM的优势,已经把Python代码扭曲成Java那样了,而且没有预先生成bytecode。
skywinger
2012-03-21 11:31:38 +08:00
@bhuztez 你好意思写出hello world的例子,这玩意只跟type在堆栈内存中的push及poll 以及io有关,能不能就写个数学计算方面的能够尽量应用cpu的样例再来比较一下??
bhuztez
2012-03-21 11:33:48 +08:00
@skywinger 我说的是启动速度,启动速度,启动速度,你看清楚点行不。
skywinger
2012-03-21 11:37:18 +08:00
@bhuztez 我不讨论启动速度不讨论启动速度,我关注的是vm的并行计算能力,高性能的内存模型。
ayanamist
2012-03-21 11:45:20 +08:00
看到楼上有小白在吹PyPy的性能了,想起以前有人说过的。一个Python程序员,能搞清楚PyPy,CPython,Jython这几个在什么场景下能达到性能最优,才可以被认为是一个优秀的Python程序员。连GIL存在的意义都没搞清楚,说JVM启动比执行速度更慢的CPython更慢来抨击JVM的,更是不知道说啥好了。
skywinger
2012-03-21 13:08:39 +08:00
@ayanamist 明白人。
vven
2012-03-21 13:33:55 +08:00
这帖窜得快啊,试用下play感觉不错,然后发现oschina上在搞play问答:)
szanlin
2012-03-21 14:14:28 +08:00
@skywinger

playframework2.0正式版才发布没有几天,楼主很迅速。我用play1.2做过私有项目,也在看关注Scala。

Scala的web框架其实还有不少:https://github.com/scalatra/scalatrahttp://liftweb.net/
skywinger
2012-03-21 14:39:22 +08:00
@szanlin play framework 很优雅,RoR的很彻底,但扩展性又比RoR好太多了,再加上JVM的执行速度与效率,确实是静态语言方面做Web的最好选择了。
bhuztez
2012-03-21 22:16:33 +08:00
@skywinger 还是总结下,一条条写

--------------------------------------------------------------
> 多说无意,还是一切以实验为主。
> JVM是否启动慢,我不知道你是从何得来的观点依据,但是,我觉得你本身就是对java及JVM有很强烈的偏见。

(我给出了实验代码)

> 我不讨论启动速度不讨论启动速度,我关注的是vm的并行计算能力,高性能的内存模型。

--------------------------------------------------------------
> 目前所有VM中最完善,速度最快,效率最高,第三方支持最多工业级的JVM

肯定不是最完善,肯定有很多方面是不如别的VM,毕竟有历史包袱在那儿。
速度最快,这个只能说是JIT做得最好,有不少情况JVM并非最快。
效率最高?效率的定义是啥?
工业级,在Erlang VM面前只能算个玩具。
--------------------------------------------------------------
> 我不相信ruby或是python会比JVM下运行的NIO程序快。

NIO就是封装了select/poll/epoll/kqueue/IOCP这样的API而已。Python/Ruby都有这些API的封装。用不用这个API,和快不快,一点关系都没有。这个只是让你能比较容易地保持更多的连接而已。运行速度还是看解释器效率的。
--------------------------------------------------------------
> 能不能就写个数学计算方面的能够尽量应用cpu的样例再来比较一下
有几个很基本浮点数运算,用gcj编译,加或者不加常用于浮点数运算的编译参数,竟然都跑不过JVM。

但是光比快,C/C++/Haskell/Fortran之类的直接编译到机器码的语言,各有擅长的领域,基于VM的,几乎可以肯定的是,无论在哪个领域,肯定比不过这其中的最适合那个领域的一种。
--------------------------------------------------------------
> 我关注的是vm的...,高性能的内存模型。
高性能内存模型,和语言/库的关系更大一点。

如果真如你所说,LMAX项目干嘛还要发明disruptor呢。
http://code.google.com/p/disruptor/
--------------------------------------------------------------
> Erlang 是process模型,Scala 是thread Actor模型,孰优孰劣,大家自然清楚。
最好看清楚点

http://en.wikipedia.org/wiki/Erlang_%28programming_language%29
> For concurrency it follows the Actor model.

Erlang在VM级别就真正实现了消息机制,而不是在这之上用别的方法去模拟。模拟会导致一个问题,一个Actor只要不主动交出控制权就可以一直占掉一个线程。

Erlang的优势还是很明显的:
每个Erlang process是独立GC的。GC延时对整个系统的运行影响很小。JVM也可以做到这样,但是,一旦你碰到GC把你卡太久的时候,你得完全理解JVM的GC是怎么工作的,理解CPU的缓存机制,再根据需要打造你需要的库。比如disruptor。用Erlang,你仅仅是损失一点点运行速度。

按照OTP风格写的代码,新版本代码替换掉旧版本代码的时候不需要停掉进程。JVM也可以做到,可是有多少库是兼容OSGi的。你用到的库不兼容OSGi,你打算都自己去改代码么。
--------------------------------------------------------------
willerce
2012-03-21 22:43:34 +08:00
其实一个刚起步的项目,最重要的是,你的团队可以什么语言来写。

咱说 asp 现在落后了,但要是有扎克的脑袋,asp 也能给写出个 fb,然后改成不是 asp,现在fb的php已经hack到不是php了吧?哦,对了,开源很重要。

以后做大了,有什么不能换呢?京东还在转 Java 呢。

喜欢就用,不喜欢就不用。多简单的事,何必如此复杂。

----------------------

玩过一段时间的 Scala,没入门,但挺喜欢的,用 Idea 敲代码还是相当不错的。
目前在做 .Net
skywinger
2012-03-22 09:22:51 +08:00
@bhuztez 真是个固执的偏执狂,我无话可说
bhuztez
2012-03-22 14:53:59 +08:00
@skywinger

其实Scala的Actor和Erlang process几乎是一样快的,但是用起来就不是那么一回事了。

下面的代码是根据这篇博客里的代码改的
http://www.krazykoding.com/2011/07/scala-actor-v-erlang-genserver.html
那里面Erlang代码用的是cast,对Scala太不公平了,所以改成call。
你可以看到,Scala还是要慢一点。

--------------------------------------------------------------
$ cat Client.scala
import scala.actors.Actor._
import scala.compat.Platform
import scala.actors.Scheduler

object Client {
val server = new Server

def main(args: Array[String]) {
runTest(3000000)
Scheduler.shutdown
}

def runTest(msgCount: Int) {
val start = Platform.currentTime
val count = test(msgCount)
val finish = Platform.currentTime
val elapsedTime = (finish - start) / 1000.0

printf("Count is %s%n",count)
printf("Test took %s seconds%n", elapsedTime)
printf("Throughput=%s per sec%n", msgCount / elapsedTime)
}

def test(msgCount: Int) :Any = {
val bytesPerMsg = 100
val updates = (1 to msgCount).foreach((x: Int) => server ! (AddCount, 1))

val count = server !? GetCount
return count
}
}

$ cat Server.scala
import scala.actors.Actor

case object GetCount
case object AddCount

class Server extends Actor {
var count: Int = 0

def act() {
react {
case GetCount =>
reply(count)
act
case (AddCount, c: Int) =>
count=count+c
act
}
}
start()
}

$ cat client.erl
-module(client).

-export([runTest/1, start/0, start/1, main/1]).


start() ->
main([]).

start(Args) ->
main(Args).

main(_Args) ->
runTest(3000000),
halt().

runTest(Size) ->
server:start_link(),
Start=now(),
{ok, Count} =test(Size),
Finish=now(),
server:stop(),
io:format("Count is ~p~n",[Count]),
io:format("Test took ~p seconds~n",[elapsedTime(Start,Finish)]),
io:format("Throughput=~p per sec~n",[throughput(Size,Start,Finish)]).

test(Size) ->
lists:foreach(fun (_X)-> server:add_count(1) end, lists:seq(1,Size)),
server:get_count().

elapsedTime(Start,Finish) ->
(toMicroSeconds(Finish) - toMicroSeconds(Start)) /1000000.

toMicroSeconds({MegaSeconds,Seconds,MicroSeconds}) ->
(MegaSeconds+Seconds) * 1000000 + MicroSeconds.

throughput(Size,Start,Finish) -> Size / elapsedTime(Start,Finish).

$ cat server.erl
-module(server).

-behaviour(gen_server).

-export([
start_link/0,
stop/0]).

-export([
init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3]).

-export([
add_count/1,
get_count/0]).

-define(SERVER, ?MODULE).

-record(state,{count}).

start_link() ->
gen_server:start_link({local,?SERVER}, ?MODULE, [], []).

get_count() ->
gen_server:call(?SERVER, get_count).

add_count(Count) ->
gen_server:call(?SERVER, {add_count, Count}).

stop() ->
gen_server:call(?SERVER, stop).

init(_Args) ->
{ok,#state{count=0}}.

handle_call(get_count, _From, State) ->
{reply, {ok, State#state.count}, State};

handle_call({add_count, Count}, _From, State) ->
{reply, ok, State#state{count=State#state.count+Count}};

handle_call(stop, _From, State) ->
{stop, normal, ok, State}.

handle_cast(_Msg, State) ->
{noreply, State}.

handle_info(_Msg, State) ->
{noreply, State}.

terminate(_Reason, _State) ->
ok.

code_change(_OLdVersion, State, _Extra) ->
{ok,State}.

$ time scalac Client.scala Server.scala

real 0m7.553s
user 0m12.683s
sys 0m0.372s
$ time erlc client.erl server.erl

real 0m0.223s
user 0m0.169s
sys 0m0.050s
$ scala Client
Count is 3000000
Test took 10.67 seconds
Throughput=281162.1368322399 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.154026 seconds
Throughput=367916.4133153365 per sec
$ scala Client
Count is 3000000
Test took 8.98 seconds
Throughput=334075.72383073496 per sec
$ scala Client
Count is 3000000
Test took 9.076 seconds
Throughput=330542.0890260026 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.083946 seconds
Throughput=371105.89308736107 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.09488 seconds
Throughput=370604.6290988872 per sec
$ scala Client
Count is 3000000
Test took 9.326 seconds
Throughput=321681.3210379584 per sec
$ scala Client
Count is 3000000
Test took 10.705 seconds
Throughput=280242.8771602055 per sec
$ scala Client
Count is 3000000
Test took 9.165 seconds
Throughput=327332.24222585926 per sec
$ scala Client
Count is 3000000
Test took 9.992 seconds
Throughput=300240.192153723 per sec
$ scala Client
Count is 3000000
Test took 9.043 seconds
Throughput=331748.31361273915 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.100325 seconds
Throughput=370355.51042705076 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.127942 seconds
Throughput=369097.1220021009 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.092804 seconds
Throughput=370699.6981515925 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.117081 seconds
Throughput=369590.98966734466 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.104893 seconds
Throughput=370146.7743004133 per sec
$ scala Client
Count is 3000000
Test took 10.224 seconds
Throughput=293427.23004694836 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.11626 seconds
Throughput=369628.3756311404 per sec
$ erl -noshell -s client
Count is 3000000
Test took 8.120545 seconds
Throughput=369433.3323687019 per sec
$ scala Client
Count is 3000000
Test took 10.094 seconds
Throughput=297206.2611452348 per sec
$
amtb
2012-03-22 15:24:44 +08:00
没有万金油语言,只有最适合的,github 用erland,因为erland可以满足他们的需求,并且他们喜欢这种语言,java无疑是现在工业标准,jvm的启动速度快慢,并不是最致命,开发效率,协作能力,都是团队要考虑的,虽然现在java相比新兴的动态语言,感觉笨重了很多,但是在当年,的确是小清新啊
amtb
2012-03-22 15:27:44 +08:00
另外,play我一直在用,从1.0开始,现在升级到2.0感觉快速开发的优势减弱了,scala的Anorm,感觉数据层的访问回到了jdbc时代,不过终于可以多数据源了。
muxi
2012-03-22 16:51:40 +08:00
@iwinux 此言差矣,这年头谁怕谁,
为什要跟捍卫Python的人说Scala多么优秀?
为什么要跟喜欢Rails的人说PHP也能做到?

这对于我们的进步和工作没有任何的帮助
任何语言在我眼里就是一个实现想法和创意的工具,什么能快速、稳定、高效的实现就去用什么,我自问不是一个编程语言的研究者,我是一个工程师,不是一个研究员。我也没打算成为一个研究员。

人生苦短,何不把有限的时间做点自己想做的事情
iwinux
2012-03-22 20:18:11 +08:00
@muxi

讨论的目的不是为了说服别人,不是为了传道,而是为了跟别人交换*有用的*信息。比如我说 Vim 好用,你说 Emacs 更强大,我看到之后可能会问“Emacs 哪里好用了?它都不能XXXX”——我这样回复,并不是为了贬低 Emacs,更不是为了捍卫 Vim,而是真的想知道它有什么优点,并且如果有可能的话会去试用。

人生苦短,所以更要见识多一点自己的框框之外的东西。显然楼上的很多人都没有理解这一点。
vven
2012-03-22 20:30:36 +08:00
@iwinux 赞同,为了避免不必要的麻烦现在我每次觉得有歧义都加一句“真心请教了”
muxi
2012-03-22 21:44:18 +08:00
@iwinux

“Emacs 哪里好用了?它都不能XXXX”

======

这样的话在我看来似乎用处不大,理由很简单,如果Emacs 真的不能XXXX,而且又没有解决方案,那么这个XXXX功能就是在别人看来就是没用的,或者大部分Emacs用户几乎用不到,如果Emacs 本身没有XXXX功能,但是这个功能又是必须的,或许有其他的实现方式,只是非Emacs 不了解而已。如果都没有,那大不了就混合方案么,又没人说Emacs就不能用vim,这跟我当年写HTML 用dreamwave,写PHP用vim一样,这就跟现在很多团队PHP + Python, PHP+JAVA , php+C++一样,什么场合用什么东西,都只是工具,了解即可,未必需要拿出来说一句:它都不能XXXX,而引发没必要的口水。

真正值得拿来说的,是扬长避短的混合架构实施方案

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/30132

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX