Skip to content

Instantly share code, notes, and snippets.

@amutake
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save amutake/c06cd8e647de62748c9e to your computer and use it in GitHub Desktop.
Save amutake/c06cd8e647de62748c9e to your computer and use it in GitHub Desktop.
ring-benchmarks
# 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'
-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.
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
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