@
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
$