ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Vert.x 가 좋다! (제 3회: Event Loops와 Verticle Instances)
    JAVA 2013. 12. 13. 12:31
    반응형

    아래 글은 일본의 acro-engineer.hatenablog.com 사이트에 올라온 글을 번역한 것입니다.

    사내 세미나 준비를 하면서 매우 많은 도움을 받은 사이트입니다. Vert.x 에 대해 이해하기 쉽게 작성되어 있어 관심있는 분들께 도움이 되길 바라는 마음에 번역해서 올립니다. 

    ※ 번역은 구글이 했습니다. 전 단지 문맥상 이상한 것만 수정했을 뿐입니다.

    id:KenichiroMurata 입니다.

    여러분, Vert.x 사용하고 있습니까?

    "Vert.x가 좋다! (제 2 회 : 개발 환경 구축) - Taste of Tech Topics"에 이어 이번에는 Vert.x 의 Event Loops와 Verticle Instances에 대해 작성했습니다.

    목차는 다음과 같습니다.

    1. Vert.x 's Threads
    2. Event Loops
    3. Verticle Instances
    4. Event Loops & Verticle Instances
    5. Performance Test 

    1. Vert.x 's Threads

    우선 Vert.x 스레드가 어떻게되어 있는지 확인해봅시다. 이전에도 이용한 HelloWorldVerticle을 이용하여 원격 디버깅 에 의해 break point에서 중지하고 실행중인 스레드를 볼수 있습니다. 

    그림과 같이, main thread가 1 개, vert.x-eventloop-thread가 0-3 4 개, vert.x-worker-thread가 0 ~ 19의 20 개가 작동하고 있다는 것을 알 수 있습니다.

    eventloop-thread에 주목합시다. 기본적으로 4 개의 eventloop-thread가 작동하고 있습니다. Event Loop가 하나인 node.js와 Vert.x가 다른 점이 지요.



    2. Event Loops

    자, 그럼 왜 eventloop-thread 4 개있는 것일까요?. 이것은 Vert.x 소스를 확인하면 알 수 있습니다. 봐야할 소스는 VertxExecutorFactory. java 입니다.

      public static EventLoopGroup eventLoopGroup(String poolName) {
         int poolSize = Integer.getInteger("vertx.pool.eventloop.size", Runtime.getRuntime().availableProcessors());
         return new NioEventLoopGroup(poolSize, new VertxThreadFactory(poolName));
       }


      Runtime.getRuntime().availableProcessors ()

    Vert.x에서 CPU의 프로세서 수를 판별하여 해당 환경에 맞는 eventloop-thread의 수가되도록 구현되어 있습니다.

    실제로 내 환경에서 다음과 같이 확인 해 보면 cpu.thread_count가 4이므로, (2core 하이퍼 스레딩 4core 상당 보이기 위하여), eventloop-thread도 4 개가 되는 것 같습니다. 

    ken @ my-vertx-module $ sysctl-a machdep.cpu
     (생략)
     machdep.cpu.core_count : 2
     machdep.cpu.thread_count : 4



    3. Verticle Instances

    한편, 공식 사이트의 문서 를 보면 vertx 명령어로 Verticle 및 Module을 실행할 때 "-instances" 옵션을 지정하여 Vertilcle 및 Module의 인스턴스 수를 지정 하여, 코어 수에 따라 응용 프로그램을 확장 할 수있다. 라고 쓰여져 있습니다.

    아무 생각없이 "-instances 10" 로 지정하고 vertx 명령을 실행하여 봅시다. 

      ken @ my-vertx-module $ vertx runmod com.mycompany~my-module~0.0.1-cp bin-instances 10
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.
     Verticle start.

    보시는 바와 같이 10 개의 HelloWorldVerticle의 인스턴스 가 생성되고 작동하는 것을 알 수 있습니다. 이것도 실제로 Vert.x 소스를 확인하면 알 수 있습니다. 봐야할 소스는 DefaultPlatformManager.java 입니다.

          for (int i = 0; i < instances; i++) {
            // Launch the verticle instance
            Runnable runner = new Runnable() {
              public void run() {
                Verticle verticle;
                try {
                  verticle = verticleFactory.createVerticle(main);
                } catch (Throwable t) {
                  handleDeployFailure(t, deploymentID, aggHandler);
                  return;
                }
                try {
                  addVerticle(deployment, verticle, verticleFactory, modID, main);
                  setPathResolver(modID, modDir);
                  DefaultFutureResult<Void> vr = new DefaultFutureResult<>();
                  verticle.start(vr);
                  vr.setHandler(new Handler<AsyncResult<Void>>() {
                    @Override
                    public void handle(AsyncResult<Void> ar) {
                      if (ar.succeeded()) {
                        aggHandler.complete();
                      } else {
                        handleDeployFailure(ar.cause(), deploymentID, aggHandler);
                      }
                    }
                  });
                } catch (Throwable t) {
                  handleDeployFailure(t, deploymentID, aggHandler);
                }
              }
            };

            if (worker) {
              vertx.startInBackground(runner, multiThreaded);
            } else {
              vertx.startOnEventLoop(runner);
            }
          }

    이 밖에 관련된 다음의 소스를 보면 대략적인 동작을 알 수 있습니다.

    Verticle를 생성 할 때 EventLoopGroup에서 하나의 eventloop-thread를 가져옵니다. 대상 Verticle에 대응시켜 그 조합을 보유하고 있습니다. 이로 인해 하나의 Verticle 인스턴스는 처음에 맵핑 된 eventloop-thread에서만 호출되는것이 보증됩니다.

    Verticle을 개발할 때 다른 스레드에서 호출 할 수 없기 때문에 동기화등을 생각하지 않고 간단한 코드를 작성할 수 있다는 Vert.x의 특징은 이렇게 실현되고 있습니다. 



    4. Event Loops & Verticle Instances

    여기까지의 내용에서 Event Loops와 Verticle Instances의 관계에 대해 정리해 보겠습니다.

    • Event Loops는 환경의 코어 수에 따라 스레드 수가 정해진다.
    • Vertcile Instances는 "-instances"옵션을 지정해서 인스턴스 수가 정해진다.
    • 하나의 Verticle 인스턴스 가 생성 될 때 Event Loops에서 하나의 eventloop-thread를 할당한다.

    예를 들어, 4 개의 eventloop-thread에 대해 10 개의 Verticle 인스턴스 를 생성 한 경우

    • vertx-eventloop-thread-0
      • Vertcile-0
      • Vertcile-4
      • Vertcile-8
    • vertx-eventloop-thread-1
      • Vertcile-1
      • Vertcile-5
      • Vertcile-9
    • vertx-eventloop-thread-2
      • Vertcile-2
      • Vertcile-6
    • vertx-eventloop-thread-3
      • Vertcile-3
      • Vertcile-7

    이렇게 할당됩니다 (어디 까지나 예입니다).

    여기서 생각해 봅시다.

    Verticle를 여러 인스턴스 생성 해 처리 규모시키고 싶다고해도 실제로는 Event Loops 스레드 수보다 멀티쓰레드로 처리 할 수 없기 때문에 Event Loops 스레드 수 이상의 Verticle Instances를 지정해도 효과가 없을것 같습니다.



    5. Performance Test

    실제로 성능 측정을 수행해 봅시다. 내 환경에서 eventloop-thread 4 개이므로, Verticle의 인스턴스 수를 1,2,4,8로 변화시킨 경우의 처리 성능을 측정하고 그 차이를 확인하고 싶습니다. (주의 :이 측정은 어디 까지나 나의 환경에서 각 조건에서의 성능을 상대적으로 확인하는 것이며, Vert.x의 성능 값을 평가하는 것은 아닙니다) 

    5.1 사전 준비

    측정에 사용하는 것은 HelloWorldVerticle입니다. 클라이언트의 요청을 시뮬레이트하기 위해 Http Performance example의 Client 를 사용합니다.

    또한 OS의 튜닝으로 maxfiles, somaxconn를 적당한 크기로 설정합니다. 

      ken @ my-vertx-module $ launchctl limit
     (생략)
         maxfiles 65535 65535         
     ken @ my-vertx-module $ sysctl-a | grep somax
     kern.ipc.somaxconn : 2048

    5.2 검증 절차

    우선 서버를 시작합니다.

    ken@my-vertx-module $ vertx runmod com.mycompany~my-module~0.0.1 -cp bin (-instances 2/4/8)

    클라이언트는 다른 터미널을 2 개 열고 각각 다음을 수행합니다.

    ken@java $ vertx run perf/RateCounter.java -cluster
    Starting clustering...
    No cluster-host specified so using address 10.0.1.6


    ken@java $ vertx run httpperf/PerfClient.java -instances 4 -cluster
    Starting clustering...
    No cluster-host specified so using address 10.0.1.6

    부하를 걸기 위해 클라이언트 측도 "-instances 4"를 사용하여 멀티 코어를 사용하도록하고 있습니다.

    PerfClient 1 인스턴스 근처 100 연결하기 위해 총 400 연결을 동시에 수행 요청을 보냅니다.

    5.3 측정 결과

    5.3.1 Verticle 인스턴스 수 1 ( "-instances"지정 없음) 

    71968 Rate: count/sec: 124666.66666666667 Average rate: 120609.15962650067
    74968 Rate: count/sec: 124666.66666666667 Average rate: 120771.52918578594
    77968 Rate: count/sec: 123333.33333333333 Average rate: 120870.10055407346
    80967 Rate: count/sec: 125375.12504168056 Average rate: 121036.96567737473
    83967 Rate: count/sec: 123333.33333333333 Average rate: 121119.01104005145
    86967 Rate: count/sec: 123333.33333333333 Average rate: 121195.39595478745
    89967 Rate: count/sec: 126000.0 Average rate: 121355.60816743918
    92967 Rate: count/sec: 126000.0 Average rate: 121505.48043929566
    95968 Rate: count/sec: 123958.68043985339 Average rate: 121582.19406468823
    98968 Rate: count/sec: 125333.33333333333 Average rate: 121695.9017056018

    5.3.2 Verticle 인스턴스 수 2 ( "-instances 2")

    72824 Rate: count/sec: 179393.13104368123 Average rate: 168241.23915192793
    75825 Rate: count/sec: 176607.79740086637 Average rate: 168572.37059017475
    78825 Rate: count/sec: 178666.66666666666 Average rate: 168956.54931810973
    81825 Rate: count/sec: 176000.0 Average rate: 169214.78765658417
    84825 Rate: count/sec: 178000.0 Average rate: 169525.49366342468
    87825 Rate: count/sec: 172000.0 Average rate: 169610.01992598918
    90825 Rate: count/sec: 171333.33333333334 Average rate: 169666.94192127718
    93825 Rate: count/sec: 175333.33333333334 Average rate: 169848.12150279776
    96825 Rate: count/sec: 178000.0 Average rate: 170100.69713400464
    99825 Rate: count/sec: 176666.66666666666 Average rate: 170298.02153769095

    5.3.3 Verticle 인스턴스 수 4 ( "-instances 4")

    72069 Rate: count/sec: 189270.24325224926 Average rate: 173805.6584661921
    75068 Rate: count/sec: 190730.24341447148 Average rate: 174481.8031651303
    78068 Rate: count/sec: 190000.0 Average rate: 175078.13700876158
    81068 Rate: count/sec: 189333.33333333334 Average rate: 175605.66438052006
    84069 Rate: count/sec: 191936.02132622458 Average rate: 176188.60697760174
    87068 Rate: count/sec: 190063.3544514838 Average rate: 176666.51352965497
    90068 Rate: count/sec: 188666.66666666666 Average rate: 177066.21663631924
    93069 Rate: count/sec: 193268.91036321226 Average rate: 177588.6707711483
    96068 Rate: count/sec: 193397.79926642214 Average rate: 178082.19178082192
    99068 Rate: count/sec: 192666.66666666666 Average rate: 178523.84220939153

    5.3.4 Verticle 인스턴스 수 8 ( "-instances 8")

    70314 Rate: count/sec: 185333.33333333334 Average rate: 161646.32932275222
    73315 Rate: count/sec: 186604.4651782739 Average rate: 162667.93971220078
    76314 Rate: count/sec: 186728.90963654552 Average rate: 163613.4916267002
    79313 Rate: count/sec: 187395.79859953318 Average rate: 164512.7532686949
    82314 Rate: count/sec: 184605.1316227924 Average rate: 165245.28026824113
    85313 Rate: count/sec: 186728.90963654552 Average rate: 166000.492304807
    88314 Rate: count/sec: 186604.4651782739 Average rate: 166700.63636569513
    91315 Rate: count/sec: 177940.68643785405 Average rate: 167070.0323057548
    94314 Rate: count/sec: 179393.13104368123 Average rate: 167461.882647327
    97314 Rate: count/sec: 178666.66666666666 Average rate: 167807.3041905584


    5.4 정리

    • (1) Verticle 인스턴스 가 1 인 경우는 약 120K count / sec
    • (2) Verticle 인스턴스 가 2 인 경우는 약 170K count / sec
    • (3) Verticle 인스턴스 가 4 인 경우는 약 190K count / sec
    • (4) Verticle 인스턴스 가 8 인 경우는 약 180K count / sec

    (1)에 비해 (2)는 2 개의 eventloop-thread로 처리하고 있기 때문에 처리 성능이 향상하고 있습니다.

    (2)와 (3)에서 (3) 쪽이 성능은 확실히 향상하고 있지만 증가는 예상보다 낮아지고 있습니다. 그러나 이것은 (2)의 시점에서 CPU 사용률이 이미 80 ~ 90 % 가까이되어 더 이상 성능을 낼 수없는 상황에있는 것으로 생각됩니다.

    (4)는 (3)에 비해 성능이 떨어지고 있습니다. Verticle의 인스턴스 수가 eventloop-thread 수보다 큰 수 역으로 처리 성능을 악화시키고 있는지, 시스템 리소스의 문제인지는 모르겠지만 더 성능이 향상되지 않는다는 점은 알았습니다.

    이렇게 말하는 것으로, Event Loops와 Verticle Instances의 관계에 대해 확인했습니다.

    Vert.x하여 응용 프로그램 개발에서 처리 성능을 끌어 내고 싶은 경우에는 Event Loop의 수와 Vertcile의 인스턴스 수에 관한 지금까지 봐 온 관계를 머리에 넣으면서 개발하는 것이 중요합니다.

    반응형
Designed by Tistory.