비동기적으로 작동하는 이벤트(Actor메시지)의 성능을 유닛테스트기를 활용하여 측정할수 있는 방법을 소개합니다.

이 샘플에서는 액터성능 테스트가 예시되어있지만 액터모델과 상관없이  유닛테스트내에서 심플한 측정모드를 이용할수 있습니다.



테스트 탐색기


테스트 탐색기를 통해 성능유닛 테스트를 수행하고 측정할수 있습니다.


여기서 설명하는 작동코드는 깃헙을 통해서도 확인할수 있으며

추가로 다양한 액터모델을 테스트하고 학습할수 있는 코드를 지속 업데이트 예정입니다.

git : 


기본 유닛테스트


        [Theory(DisplayName = "RoundRobinPoolTest")]
        [InlineData(3,1000)]
        public void RoundRobinPoolTest(int nodeCount, int testCount, bool isPerformTest = false)
        {
            var actorSystem = akkaService.GetActorSystem();

            TestProbe testProbe = this.CreateTestProbe(actorSystem);

            var props = new RoundRobinPool(nodeCount)                
                .Props(Props.Create(() => new BasicActor()));

            var actor = actorSystem.ActorOf(props);

            for (int i = 0; i < nodeCount; i++)
            {
                actor.Tell(testProbe.Ref);
            }

            int cutOff = 3000;

            Within(TimeSpan.FromMilliseconds(cutOff), () =>
            {
                for (int i = 0; i < testCount; i++)
                {
                    actor.Tell("hello" + i);
                }

                for (int i = 0; i < testCount; i++)
                {
                    testProbe.ExpectMsg("world");
                    
                    if (isPerformTest)
                    {
                        _dictionary.Add(_key++, _key);
                        _addCounter.Increment();
                    }
                }
            });
        }


측정을 위해서는 비동기적으로 발생하는 이벤트가 완료되었다란 정의를 어떻게 내리고 측정을 해야할까요?

위코드는 단순하게 이벤트 생성에서만 측정하는것이아닌 메시지함에서 확인함까지 완료하는 검증로직이며

Message delivery once 수준을 검증 합니다.


Akka테스트 툴킷

메시지 수신함에서 메시지가 있는지를 하나씩 꺼내 체크하는 Akka Testkit이 제공하는 큐검사 방식으로

핵심로직을 블락을 시키지 않고 검사할수 있는 방법입니다.

testProbe.ExpectMsg("world");



Nbench에서 지원하는 함수로 수신검사가 완료되면 성능카운터를 1 증가합니다.

성능 테스트모드일때만 수행할수 있으며 기본 유닛테스트에서는 성능테스트 제외하여 도메인검증에 집중할수 있습니다.

_addCounter.Increment();



유닛테스트가 완료된 로직의 성능테스트가 필요시 Nbench를 활용하여 성능 유닛테스트 검사기를 추가할수 있습니다.

        [NBenchFact]        
        [PerfBenchmark(NumberOfIterations = 3, RunMode = RunMode.Throughput,
        RunTimeMilliseconds = 1000, TestMode = TestMode.Test)]
        [CounterThroughputAssertion("TestCounter", MustBe.GreaterThan, 1000.0d)]
        [CounterTotalAssertion("TestCounter", MustBe.GreaterThan, 1500.0d)]
        [CounterMeasurement("TestCounter")]
        public void RoundRobinPoolTestPerformanceTest()
        {
            RoundRobinPoolTest(5, 3000, true);
        }

주요 설정 옵션은 다음과 같습니다.



성능 유닛트세트가 작성되면, VS-IDE가 제공하는 테스트 탐색기를 통해서도 수행할수 있습니다.



성능측정 리포트


    [PASS] Expected [Counter] TestCounter to must be greater than 1,000.00 operations; actual value was 94,160.06 operations.
    
    [PASS] Expected [Counter] TestCounter to must be greater than 1,500.00 operations; actual value was 93,000.00 operations.
    
    
    ---------- Measurements ----------
    
    Metric : [Counter] TestCounter
    
    Per Second ( operations )
    Average         : 94160.06329051661
    Max             : 94937.13528317196
    Min             : 93266.78965179897
    Std. Deviation  : 841.2138544819605
    Std. Error      : 485.6750453312026
    
    Per Test ( operations )
    Average         : 93000
    Max             : 93000
    Min             : 93000
    Std. Deviation  : 0
    Std. Error      : 0
    
    ----------

성능측정이 통과가 되면 간단한 리포팅이 표시가 되며 성능측정이 통과유무의 정보가 표현됩니다.



참고링크 :