Last active
August 29, 2015 14:02
-
-
Save amutake/c06cd8e647de62748c9e to your computer and use it in GitHub Desktop.
ring-benchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Haskell | |
$ ghc -threaded -O2 ring_benchmarks.hs | |
$ time ./ring_benchmarks N T +RTS -N | |
# Erlang | |
# +P は、プロセス数の上限を上げるフラグ。デフォルトは 262144 (man erl を参照)。N >= 26212* のときはこれを有効化する。 | |
$ erlc ring_benchmarks.erl | |
$ time erl (+P N+1) -noshell -eval "ring_benchmarks:start(N, T)." -s init stop | |
# Scala | |
# build.sbt などを用意する | |
$ sbt compile | |
$ time sbt 'run N T' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(ring_benchmarks). | |
-export([start/2]). | |
start(N, T) -> | |
Self = self(), | |
RootId = spawn(fun() -> ring_root(Self, T) end), | |
NodeIds = create_nodes(N - 1), | |
lists:map(fun({Id1, Id2}) -> Id1 ! {next, Id2} end, lists:zip([RootId|NodeIds], lists:append(NodeIds, [RootId]))), | |
RootId ! ok, | |
receive | |
ok -> io:write(ok) | |
end. | |
create_nodes(0) -> []; | |
create_nodes(N) -> | |
[spawn(fun() -> ring_node() end)|create_nodes(N - 1)]. | |
ring_root(Master, Times) -> | |
receive | |
{next, Next} -> | |
root_loop(Master, Next, Times) | |
end. | |
root_loop(Master, _, 0) -> Master ! ok; | |
root_loop(Master, Next, Times) -> | |
receive | |
ok -> | |
Next ! ok, | |
root_loop(Master, Next, Times - 1) | |
end. | |
ring_node() -> | |
receive | |
{next, Next} -> | |
node_loop(Next) | |
end. | |
node_loop(Next) -> | |
receive | |
ok -> | |
Next ! ok, | |
node_loop(Next) | |
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main (main) where | |
-- required package: base, distributed-process, network-transport-tcp | |
import Control.Applicative ((<$>)) | |
import Control.Distributed.Process (Process, ProcessId, send, expect, getSelfPid, spawnLocal, liftIO) | |
import Control.Distributed.Process.Node (newLocalNode, initRemoteTable, runProcess) | |
import Control.Monad (forM_, replicateM) | |
import Network.Transport.TCP (createTransport, defaultTCPParameters) | |
import System.Environment (getArgs) | |
main :: IO () | |
main = do | |
(n : t : []) <- map read <$> getArgs | |
Right transport <- createTransport "localhost" "12345" defaultTCPParameters | |
localnode <- newLocalNode transport initRemoteTable | |
runProcess localnode (master n t) | |
master :: Int -> Int -> Process () | |
master n t = do | |
rootId <- makeRing n t | |
send rootId () | |
_unit <- expect :: Process () | |
liftIO $ putStrLn "finish" | |
makeRing :: Int -> Int -> Process ProcessId | |
makeRing n t = do | |
me <- getSelfPid | |
rootId <- spawnLocal $ root me t | |
nodeIds <- replicateM (n - 1) $ spawnLocal node | |
forM_ ((rootId : nodeIds) `zip` (nodeIds ++ [rootId])) $ \(id1, id2) -> send id1 id2 | |
return rootId | |
root :: ProcessId -> Int -> Process () | |
root master times = do | |
next <- expect | |
loop next times | |
where | |
loop _ 0 = send master () | |
loop next t = do | |
unit <- expect :: Process () | |
send next unit | |
loop next (t - 1) | |
node :: Process () | |
node = do | |
next <- expect | |
loop next | |
where | |
loop next = do | |
unit <- expect :: Process () | |
send next unit | |
loop next |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.amutake | |
import akka.actor._ | |
object RingBenchmarks { | |
sealed trait Msg | |
case class Start(n: Int, t: Int) extends Msg | |
case class Next(next: ActorRef) extends Msg | |
case object End extends Msg | |
class MasterActor extends Actor { | |
def receive = { | |
case Start(n, t) => { | |
val rootId = makeRing(n, t) | |
rootId ! () | |
} | |
case End => { | |
println("finish") | |
context.system.shutdown | |
} | |
} | |
def makeRing(n: Int, t: Int): ActorRef = { // return value: the address of the root actor | |
val rootId = context.actorOf(Props(classOf[RootActor], t, self), "root") | |
val nodeIds = 1 to (n - 1) map { num => | |
context.actorOf(Props[NodeActor], "node" ++ num.toString) | |
} | |
(rootId +: nodeIds) zip (nodeIds :+ rootId) map { case (id1, id2) => | |
id1 ! Next(id2) | |
} | |
rootId | |
} | |
} | |
class RootActor(val init: Int, val master: ActorRef) extends Actor { | |
def receive = { | |
case Next(next) => context.become(behavior(init, next)) | |
} | |
def behavior(n: Int, next: ActorRef): Receive = { | |
case () => { | |
if (n == 0) { | |
master ! End | |
} else { | |
next ! () | |
context.become(behavior(n - 1, next)) | |
} | |
} | |
} | |
} | |
class NodeActor extends Actor { | |
def receive = { | |
case Next(next) => context.become(behavior(next)) | |
} | |
def behavior(next: ActorRef): Receive = { | |
case () => { | |
next ! () | |
} | |
} | |
} | |
def main(args: Array[String]) = { | |
val n = args(0).toInt // n 個のアクターで、 | |
val t = args(1).toInt // t 周メッセージを回す | |
val system = ActorSystem() | |
val master = system.actorOf(Props[MasterActor]) | |
master ! Start(n, t) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment