기본 콘텐츠로 건너뛰기

[Vert.x] Vertlcle, Event Loop 그리고 Thread

Vert.x 실행 할 때 Verticle 개수와 CPU 개수나 Thread 개수 연관 등이 궁금해서 잠시 테스트 해 보았다.

Vert.x의 Verticle은 Event Loop에서 동작한다. 여기서 Event Loop는 Netty의 "io.netty.channel.nio.NioEventLoop"를 말하며, NIO Selector 기반이다.


Event Loop Pool 개수는 NioEventLoop를 생성하는 개수가 된다. Event Loop Pool 개수를 지정 하지 않으면 아래가 기본 공식이다.

2 * Runtime.getRuntime().availableProcessors()

Vert.x의 Verticle은 Event Loop에서 동작한다 했다. 정확히는 Event Loop는 Single Threaded Executor이고 Verticle은 하나의 실행 Task이다. Verticle이 실행 될 때 Thread 이름과 함께 로그를 남겨 보면 Verticle을 실행한 Event Loop의 Thread를 확인 할 수 있다.

[vert.x-eventloop-thread-0               ] INFO  fs.App - !!!Start App!!!
[vert.x-eventloop-thread-1               ] INFO  fs.redis.Redis - !!!Start Redis!!!
[vert.x-eventloop-thread-2               ] INFO  fs.redis.Redis - !!!Start Redis!!!
[vert.x-eventloop-thread-3               ] INFO  fs.web.Http - !!!Start Http!!!
[vert.x-eventloop-thread-4               ] INFO  fs.web.Http - !!!Start Http!!!

코드로 Event Loop Pool 크기를 지정 할 수 있는데,

VertxOptions vertxOptions = new VertxOptions();
vertxOptions.setEventLoopPoolSize(2);
vertx = Vertx.vertx(vertxOptions);

Event Loop Pool 개수를 Verticle 개수 보다 적게 만들어 보면 하나의 Event Loop에서 여러 개의 Verticle이 실행 됨을 알 수 있다.

[vert.x-eventloop-thread-0] INFO  fs.App - !!!Start App!!! 17
[vert.x-eventloop-thread-0] INFO  fs.redis.Redis - !!!Start Redis!!! 21
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - !!!Start Redis!!! 21
[vert.x-eventloop-thread-0] INFO  fs.web.Http - !!!Start Http!!! 22
[vert.x-eventloop-thread-1] INFO  fs.web.Http - !!!Start Http!!! 22

그리고 스트레스 테스트를 해보면 Verticle 인스턴스는 처음 실행 된 Thread 에서 실행 되는 것을 알 수 있다.  (코드를 살펴보지 않아서 Event Loop가 생성 될 때 Verticle이 할당되는 것인지 실행 시점에 순차적으로 Verticle을 호출 하는 지는 알 수 없다,,)

[vert.x-eventloop-thread-2] INFO  fs.redis.Redis - !!!Start Redis!!! fs.redis.Redis@64a96df
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - !!!Start Redis!!! fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-2] INFO  fs.redis.Redis - Receive: fs.redis.Redis@64a96df
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-2] INFO  fs.redis.Redis - Receive: fs.redis.Redis@64a96df
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-2] INFO  fs.redis.Redis - Receive: fs.redis.Redis@64a96df
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe
[vert.x-eventloop-thread-1] INFO  fs.redis.Redis - Receive: fs.redis.Redis@10a7c8fe


정리하면

NIO Selector = NioEventLoop = SingleThreadEventLoop = Vert.x Event Loop의 관계가 된다. 그리고 Event Loop : Verticle = 1 : N 의 관계도 성립 되며 Event Loop에서 여러 개의 Verticle이 실행되는 것은 Single Thread Executor 에서 실행되는 여러 Task의 관계로 볼 수 있다. 그래서 꼭 Core 개수와 Verticle 개수가 일치가 성능을  좌우 하지 않음을 알 수 있다.

참고


siege -b -c100 -t 10S http://127.0.0.1:8080/vertx

-------------------------------------------------
- 4 core
- 5 verticle
- 1 event loop pool count

1회
Transactions:          8866 hits
Availability:        100.00 %
Elapsed time:          9.58 secs
Data transferred:         0.34 MB
Response time:          0.11 secs
Transaction rate:       925.47 trans/sec
Throughput:          0.04 MB/sec
Concurrency:         99.24
Successful transactions:        8866
Failed transactions:            0
Longest transaction:         0.33
Shortest transaction:         0.10

2회
Transactions:          9706 hits
Availability:        100.00 %
Elapsed time:          9.92 secs
Data transferred:         0.37 MB
Response time:          0.10 secs
Transaction rate:       978.43 trans/sec
Throughput:          0.04 MB/sec
Concurrency:         99.56
Successful transactions:        9706
Failed transactions:            0
Longest transaction:         0.16
Shortest transaction:         0.10

-------------------------------------------------
- 4 core
- 5 verticle
- 2 event loop pool count

1회
Transactions:         20908 hits
Availability:        100.00 %
Elapsed time:          9.55 secs
Data transferred:         0.80 MB
Response time:          0.05 secs
Transaction rate:      2189.32 trans/sec
Throughput:          0.08 MB/sec
Concurrency:         99.52
Successful transactions:       20908
Failed transactions:            0
Longest transaction:         0.25
Shortest transaction:         0.00

2회
Transactions:         22316 hits
Availability:        100.00 %
Elapsed time:          9.94 secs
Data transferred:         0.85 MB
Response time:          0.04 secs
Transaction rate:      2245.07 trans/sec
Throughput:          0.09 MB/sec
Concurrency:         99.45
Successful transactions:       22316
Failed transactions:            0
Longest transaction:         0.11
Shortest transaction:         0.00

-------------------------------------------------
- 4 core
- 5 verticle
- 8 event loop pool count

1회
Transactions:         19887 hits
Availability:        100.00 %
Elapsed time:          9.04 secs
Data transferred:         0.76 MB
Response time:          0.05 secs
Transaction rate:      2199.89 trans/sec
Throughput:          0.08 MB/sec
Concurrency:         99.67
Successful transactions:       19887
Failed transactions:            0
Longest transaction:         0.14
Shortest transaction:         0.00

2회
Transactions:         21064 hits
Availability:        100.00 %
Elapsed time:          9.38 secs
Data transferred:         0.80 MB
Response time:          0.04 secs
Transaction rate:      2245.63 trans/sec
Throughput:          0.09 MB/sec
Concurrency:         99.35
Successful transactions:       21064
Failed transactions:            0
Longest transaction:         0.11
Shortest transaction:         0.00

테스트 코드


댓글