LoginSignup
9
7

More than 5 years have passed since last update.

Akka-HTTP vs Spray ベンチマーク取ってみた

Last updated at Posted at 2016-04-16

ブログのコピペです。

今回は前回紹介したAkka-HTTPの性能が気になったのでざっくりベンチマークを取ってみました。
ソースコードはGithubにあげました。

それぞれのバージョン等は以下の通りです。

build.sbt
// sbt.version = 0.13.11
// addSbtPlugin("io.spray" % "sbt-revolver" % "0.8.0")
// addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.2")

lazy val commonSettings = Seq(
  name := "akka-http-vs-spray",
  version := "1.0.0",
  scalaVersion := "2.11.8",
  scalacOptions := Seq("-unchecked", "-deprecation", "-encoding", "utf8", "-Xlint")
)

val akkaV = "2.4.4"
val sprayV = "1.3.3"

lazy val spraySettings = Seq(
  libraryDependencies ++= {
    Seq(
      "com.typesafe.akka"   %%  "akka-actor"    % akkaV,
      "io.spray"            %%  "spray-can"     % sprayV,
      "io.spray"            %%  "spray-routing" % sprayV
    )
  }
)

lazy val akkaSettings = Seq(
  libraryDependencies ++= {
    Seq(
      "com.typesafe.akka" %% "akka-actor" % akkaV,
      "com.typesafe.akka" %% "akka-stream" % akkaV,
      "com.typesafe.akka" %% "akka-http-experimental" % akkaV
    )
  }
)

lazy val sprayServer = (project in file("spray-server"))
.settings(commonSettings: _*)
.settings(spraySettings: _*)
.settings(assemblyOutputPath in assembly := file("./spray-server.jar"))

lazy val akkaServer = (project in file("akka-server"))
.settings(commonSettings: _*)
.settings(akkaSettings: _*)
.settings(assemblyOutputPath in assembly := file("./akka-server.jar"))

Revolver.settings
java version "1.8.0_71"
Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)

sbt assemblyしたjarをローカルでjava -jarしてベンチマークをとりました。

ローカル環境

MacBook Pro (Retina, 13-inch, Early 2015)
OS: OSX 10.11.4
Processor: 3.1 GHz Intel Core i7
Memory: 16 GB 1867 MHz DDR3

ベンチマークにはApacheBenchを用いました。

ab -k -c 10 -n 10000 http://localhost:8080/

以下それぞれの結果です。

Akka-HTTP

Code

package akka.server

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import akka.stream.ActorMaterializer

object Boot extends App {
  implicit lazy val system = ActorSystem("akka-server")
  implicit lazy val materializer = ActorMaterializer()
  implicit val ec = system.dispatcher

  private val route =
    pathSingleSlash {
      get {
        complete("Hello world!")
      }
    }

  Http().bindAndHandle(route, "localhost", 8080)
}

Result

This is ApacheBench, Version 2.3 <$Revision: 1706008 $>

Server Software:        akka-http/2.4.4
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      10
Time taken for tests:   0.465 seconds
Complete requests:      10000
Failed requests:        0
Keep-Alive requests:    10000
Total transferred:      1780000 bytes
HTML transferred:       120000 bytes
Requests per second:    21490.49 [#/sec] (mean)
Time per request:       0.465 [ms] (mean)
Time per request:       0.047 [ms] (mean, across all concurrent requests)
Transfer rate:          3735.65 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   1.0      0      42
Waiting:        0    0   1.0      0      42
Total:          0    0   1.0      0      42

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      1
  95%      1
  98%      2
  99%      3
 100%     42 (longest request)

Spray-can

Code

package spray.server

import akka.actor._
import akka.io.IO
import spray.can.Http
import spray.routing._
import spray.http._
import akka.pattern.ask
import akka.util.Timeout
import scala.concurrent.duration._

object Boot extends App {
  implicit val system = ActorSystem("spray-server")
  implicit val timeout = Timeout(5.seconds)
  val service = system.actorOf(Props[ServiceActor], "spray-service")

  IO(Http) ? Http.Bind(service, "localhost", 8080)
}

class ServiceActor extends Actor with HttpService {
  private val route =
    pathSingleSlash {
      get {
        complete("Hello world!")
      }
    }

  def actorRefFactory = context
  def receive = runRoute(route)
}

Result

This is ApacheBench, Version 2.3 <$Revision: 1706008 $>

Server Software:        spray-can/1.3.3
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      10
Time taken for tests:   0.430 seconds
Complete requests:      10000
Failed requests:        0
Keep-Alive requests:    10000
Total transferred:      1780000 bytes
HTML transferred:       120000 bytes
Requests per second:    23230.85 [#/sec] (mean)
Time per request:       0.430 [ms] (mean)
Time per request:       0.043 [ms] (mean, across all concurrent requests)
Transfer rate:          4038.18 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   0.9      0      20
Waiting:        0    0   0.9      0      20
Total:          0    0   0.9      0      20

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      1
  95%      1
  98%      2
  99%      3
 100%     20 (longest request)

まとめ

Akka-HTTPが21490.49 req/sec、Spray-canが23230.85 req/secと割と近い数値が出た気がします。
Akka-HTTPは前もっと使い物にならないくらい遅かったイメージだったんですがこれなら十分なリクエストがさばけそうです。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7