13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaAdvent Calendar 2019

Day 24

[検証]SpringBoot vs Micronaut 起動速度の比較

Last updated at Posted at 2019-12-23

Java Advent Calendar 2019 24日目の記事です。

クリスマス前にも関わらず暇なので:rage:
JVM言語ベースのフレームワークであるSpringBootとMicronautの単純起動速度を比較してみた

Springは知る人ぞ知るフレームワークなので紹介は省きます

##Mirconautとは

  • OCI社が開発したマイクロサービス向けフレームワーク
  • JVMベース
  • 2018年10月に1.0GAリリース

公式サイト
https://micronaut.io/

###特徴

  • プログラム言語にJava/Groovy/Kotlinが使える
  • Compile Time DI&AOPを採用している
  • GraalVM、NativeImageも使える
  • CLIが提供されている
  • 起動が早い
  • メモリフットプリントが小さい

##検証
###環境

  • MacBook Pro
スクリーンショット 2019-12-23 13.45.43.png
  • SpringBoot v2.2.2.RELEASE
  • Micronaut 1.2.7

#####実行環境

  • AdoptOpenJDK 11.0.4
  • AdoptOpenJDK 8.0.232
  • GraalVM 19.2.1
  • JIT
  • AOT(NativeImage)

###方法

  • シンプルなREST APIを1つ実装する
  • jarにパッケージして起動する(java -jar xxx.jar)
  • 各実行環境で10回起動して、その平均値を取る
  • SpringBootはTomcatとJettyの両方で起動速度を計測する

###実装
####SpringBoot

@RestController
public class HelloController {

    @RequestMapping(value="/hello", method=RequestMethod.GET)
    public String hello() {
        return "Hello Spring";
    }
}

Tomcat起動

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2019-12-23 14:29:46.247  INFO 73041 --- [           main] com.example.sphelloapp.DemoApplication   : Starting DemoApplication
2019-12-23 14:29:46.250  INFO 73041 --- [           main] com.example.sphelloapp.DemoApplication   : No active profile set, falling back to default profiles: default
2019-12-23 14:29:46.925  INFO 73041 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-12-23 14:29:46.935  INFO 73041 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-12-23 14:29:46.935  INFO 73041 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.29]
2019-12-23 14:29:46.984  INFO 73041 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-12-23 14:29:46.984  INFO 73041 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 695 ms
2019-12-23 14:29:47.105  INFO 73041 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-12-23 14:29:47.214  INFO 73041 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-12-23 14:29:47.216  INFO 73041 --- [           main] com.example.sphelloapp.DemoApplication   : Started DemoApplication in 1.233 seconds (JVM running for 1.556)

Jetty起動

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.2.RELEASE)

2019-12-23 14:22:39.036  INFO 72942 --- [           main] c.e.sphelloappjetty.DemoApplication      : Starting DemoApplication
2019-12-23 14:22:39.038  INFO 72942 --- [           main] c.e.sphelloappjetty.DemoApplication      : No active profile set, falling back to default profiles: default
2019-12-23 14:22:39.651  INFO 72942 --- [           main] org.eclipse.jetty.util.log               : Logging initialized @1229ms to org.eclipse.jetty.util.log.Slf4jLog
2019-12-23 14:22:39.713  INFO 72942 --- [           main] o.s.b.w.e.j.JettyServletWebServerFactory : Server initialized with port: 8080
2019-12-23 14:22:39.716  INFO 72942 --- [           main] org.eclipse.jetty.server.Server          : jetty-9.4.24.v20191120; built: 2019-11-20T21:37:49.771Z; git: 363d5f2df3a8a28de40604320230664b9c793c16; jvm 1.8.0_232-20191009173705.graal.jdk8u-src-tar-gz-b07
2019-12-23 14:22:39.738  INFO 72942 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring embedded WebApplicationContext
2019-12-23 14:22:39.739  INFO 72942 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 664 ms
2019-12-23 14:22:39.815  INFO 72942 --- [           main] org.eclipse.jetty.server.session         : DefaultSessionIdManager workerName=node0
2019-12-23 14:22:39.815  INFO 72942 --- [           main] org.eclipse.jetty.server.session         : No SessionScavenger set, using defaults
2019-12-23 14:22:39.816  INFO 72942 --- [           main] org.eclipse.jetty.server.session         : node0 Scavenging every 660000ms
2019-12-23 14:22:39.821  INFO 72942 --- [           main] o.e.jetty.server.handler.ContextHandler  : Started o.s.b.w.e.j.JettyEmbeddedWebAppContext@45f45fa1{application,/,[file:///private/var/folders/xk/q20_p4gd2xz1sfmtmngwjg380000gp/T/jetty-docbase.146795275059491819.8080/],AVAILABLE}
2019-12-23 14:22:39.822  INFO 72942 --- [           main] org.eclipse.jetty.server.Server          : Started @1400ms
2019-12-23 14:22:39.922  INFO 72942 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-12-23 14:22:40.036  INFO 72942 --- [           main] o.e.j.s.h.ContextHandler.application     : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-12-23 14:22:40.036  INFO 72942 --- [           main] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2019-12-23 14:22:40.040  INFO 72942 --- [           main] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms
2019-12-23 14:22:40.060  INFO 72942 --- [           main] o.e.jetty.server.AbstractConnector       : Started ServerConnector@37574691{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2019-12-23 14:22:40.062  INFO 72942 --- [           main] o.s.b.web.embedded.jetty.JettyWebServer  : Jetty started on port(s) 8080 (http/1.1) with context path '/'
2019-12-23 14:22:40.064  INFO 72942 --- [           main] c.e.sphelloappjetty.DemoApplication      : Started DemoApplication in 1.299 seconds (JVM running for 1.643)

(参考)
jetty起動にする場合の設定(gradle)

build.gradle
dependencies {
    compile('org.springframework.boot:spring-boot-starter-web') {
        exclude module: 'spring-boot-starter-tomcat'
    }
    compile('org.springframework.boot:spring-boot-starter-jetty')
}

#####NativeImage起動
Springはまだ正式にはNativeImageに対応していない(2020年2Qに対応予定)
実験版がgithubにあるので、これで検証する(TomcatのみでJettyはない)
https://github.com/spring-projects-experimental/spring-graal-native

手順

  1. GitHubのspring-graal-nativeをclone
  2. ./build-feature.shを実行
  3. spring-graal-native-samples/springmvc-tomcatに移動
  4. ./compile.shを実行 (1〜2分)
スクリーンショット 2019-12-23 15.30.52.png 5. `target`フォルダに移動し、`springmvc-tomcat`が生成されていることを確認 6. `./springmvc-tomcat`で実行

これでspring側の準備は完了

####Micronaut

HelloController.java
@Controller
public class HelloController{

    @Get(value="/hello", produces = MediaType.TEXT_PLAIN)
    public String index(){
        return "Hello Micronaut";
    }
}

起動

14:37:49.383 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 985ms. Server Running: http://localhost:8080

#####NativeImage起動
Micronautは標準でNativeImageに対応しているが、NativeImage専用のプロジェクトを作ると楽できる
※前提としてMicronautCLIがインストールされていること
 Micronautインストール手順はここを参照
手順

  1. $mn create-app hello-graal --features graal-native-image
  2. HelloController.javaを実装
  3. ./gradlew buildを実行
  4. $native-image --no-server -cp build/libs/hello-graal-0.1-all.jarを実行 (1〜2分)
  5. ./hello-graalを実行

これでMicronaut側の準備は完了

##結果
図1.png
スクリーンショット 2019-12-23 16.15.25.png

###考察

  • JDK(11, 8, GraalVM JIT)では差はほぼない。
  • フレームワーク同士では約300msの差はあるが、これを大きいと捉えるか小さいと捉えるかは個人の考えやケースによる。筆者の場合は特に気にならない差である。
  • GraalVM AOT(NativeImage)は圧倒的に早い。
  • JVM上で動作させることの利点を捨ててまでNativeImageにする恩恵があるかと言われれば疑問も残る。
     (JVMも1秒前後で起動するからいいんじゃないか)
  • ただし、今回は超シンプルなアプリだった結果であるため、たくさんクラスロードがあるようなアプリだと起動時間においてはAOTの恩恵をさらに感じるかもしれない。

##最後に
今回は単純なアプリでの検証のため、実際の複雑なアプリでは異なる結果になるかもしれないので、あくまで参考として見ていただけると幸いです。
機会があればhelidonとかQuarkusといったフレームワークも検証してみます。

13
3
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
13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?