Microsoft MVP성태의 닷넷 이야기
.NET Framework: 768. BenchmarkDotNet으로 Span<T> 성능 측정 [링크 복사], [링크+제목 복사],
조회: 13511
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

BenchmarkDotNet으로 Span<T> 성능 측정

BenchmarkDotNet으로,

BenchmarkDotNet 라이브러리 소개
; https://www.sysnet.pe.kr/2/0/11547

(하다 보니 재미있어서) 이번에는 지난 글의 Span 타입의 성능을 다시 측정해 봤습니다. ^^

C# - System.Span<T> 성능
; https://www.sysnet.pe.kr/2/0/11535

Benchmark 소스 코드는 다음과 같은데,

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Runtime.InteropServices;

namespace spanBenchmark
{
    class Program
    {
        static void Main(string[] args)
        {
            BenchmarkRunner.Run<LoopTest>();
        }
    }

    public class LoopTest
    {
        private byte[] data;

        [Params(1000, 10000)]
        public int N;

        [GlobalSetup]
        public void Setup()
        {
            data = new byte[N];
            new Random(42).NextBytes(data);
        }

        [Benchmark]
        public void ForLoopTest()
        {
            MyLoop.ForLoop(data);
        }

        [Benchmark]
        public void SpanLoopTest()
        {
            MyLoop.SpanLoop(data);
        }

        [Benchmark]
        public void PtrLoopTest()
        {
            MyLoop.PtrLoop(data);
        }
    }


    class MyLoop
    {
        public static int ForLoop(byte[] buffer)
        {
            int sum = 0;

            for (int i = 0; i < buffer.Length; i++)
            {
                sum += buffer[i];
            }

            return sum;
        }

        public static int SpanLoop(byte[] buffer)
        {
            Span<byte> span = buffer;
            int sum = 0;
            for (int i = 0; i < span.Length; i++)
            {
                sum += span[i];
            }
            return sum;
        }

        public static unsafe int PtrLoop(byte[] buffer)
        {
            int sum = 0;

            fixed (byte* ptr = buffer)
            {
                for (int i = 0; i < buffer.Length; i++)
                {
                    sum += *(ptr + i);
                }
            }
            return sum;
        }
    }
}

보는 바와 같이 이번에는 Params와 GlobalSetup 특성도 사용해 봤습니다. ^^ 다음은 그 결과입니다.

// * Summary *

BenchmarkDotNet=v0.10.14, OS=Windows 10.0.17134
Intel Core i5-4670 CPU 3.40GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=2.2.0-preview1-007877
  [Host]     : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
  DefaultJob : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT


       Method |     N |       Mean |     Error |    StdDev |
------------- |------ |-----------:|----------:|----------:|
  ForLoopTest |  1000 |   435.1 ns |  7.530 ns |  8.370 ns |
 SpanLoopTest |  1000 |   447.5 ns |  3.363 ns |  2.808 ns |
  PtrLoopTest |  1000 |   435.2 ns |  3.598 ns |  3.004 ns |
  ForLoopTest | 10000 | 4,300.5 ns | 37.432 ns | 35.013 ns |
 SpanLoopTest | 10000 | 4,416.1 ns | 82.525 ns | 73.156 ns |
  PtrLoopTest | 10000 | 4,296.7 ns | 28.328 ns | 26.498 ns |

Params 특성에 따라 N에 따른 배열의 크기가 1000, 10000인 경우로 나뉘어 측정이 되었습니다. 이번 결과에서도 확인이 되지만 공용 indexer 속성을 통해 제공하는 Span 타입의 액세스가,

Span<byte> span = buffer;
int sum = 0;
for (int i = 0; i < span.Length; i++)
{
    sum += span[i];
}

배열 인스턴스로 다루는 것과 비교해도 밀리지 않는 성능을 보이고 있습니다.




참고로 BenchmarkDotNet은 테스트 이후의 결과물을 \bin\Release\ 폴더 하위에 \BenchmarkDotNet.Artifacts\results 폴더로 csv, html, md 파일 포맷으로 함께 출력해 줍니다.

또한 RPlotExporter 특성을 적용해 주면,

[RPlotExporter]
public class LoopTest
{
    ...[생략]...
}

다양한 그래픽 출력을 해주는 R 스크립트 파일을 \results 폴더에 생성해 줍니다. 이 파일을 실행해 보고 싶다면 다음의 글에 따라 구성을 하면 됩니다.

BenchmarkDotNet에서 생성한 BuildPlots.R 파일을 실행하는 방법
; https://www.sysnet.pe.kr/2/0/11549




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/13/2018]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2020-10-07 09시31분
[HelloWorld] 안녕하세요. 글 잘 읽고 갑니다. 해당 내용 기반으로 성능 테스트를 해보니 위와 같은 결과가 나오지 않아서요. 실행환경은 .Net Framework 4.7, WPF Proejct입니다.
저의 경우는 SpanLoopTest의 속도가 2배가까이 느린걸로 나왔네요. 코드는 위와 동일하게 사용했습니다.!

| Method | N | Mean | Error | StdDev |
|------------- |------ |-----------:|---------:|---------:|
| ForLoopTest | 1000 | 311.9 ns | 1.77 ns | 1.66 ns |
| SpanLoopTest | 1000 | 933.4 ns | 4.00 ns | 3.74 ns |
| PtrLoopTest | 1000 | 328.6 ns | 6.33 ns | 7.54 ns |
| ForLoopTest | 10000 | 3,061.8 ns | 15.41 ns | 13.66 ns |
| SpanLoopTest | 10000 | 9,336.1 ns | 72.35 ns | 67.67 ns |
| PtrLoopTest | 10000 | 3,233.0 ns | 41.69 ns | 38.99 ns |
[guest]
2020-10-07 09시56분
(본문에 언급해 두었던) 아래의 글에 이미 설명을 했었습니다.

C# - System.Span<T> 성능
; https://www.sysnet.pe.kr/2/0/11535
정성태

... 31  32  33  34  35  [36]  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
12730정성태7/23/20219063개발 환경 구성: 583. Visual Studio Code - Go 코드에서 입력을 받는 경우
12729정성태7/22/20218011.NET Framework: 1080. xUnit 단위 테스트에 메서드/클래스 수준의 문맥 제공 - Fixture
12728정성태7/22/20217497.NET Framework: 1079. MSTestv2 단위 테스트에 메서드/클래스/어셈블리 수준의 문맥 제공
12727정성태7/21/20218457.NET Framework: 1078. C# 단위 테스트 - MSTestv2/NUnit의 Assert.Inconclusive 사용법(?) [1]
12726정성태7/21/20218289VS.NET IDE: 169. 비주얼 스튜디오 - 단위 테스트 선택 시 MSTestv2 외의 xUnit, NUnit 사용법 [1]
12725정성태7/21/20217013오류 유형: 741. Failed to find the "go" binary in either GOROOT() or PATH
12724정성태7/21/20219700개발 환경 구성: 582. 윈도우 환경에서 Visual Studio Code + Go (Zip) 개발 환경 [1]
12723정성태7/21/20217322오류 유형: 740. SharePoint - Alternate access mappings have not been configured 경고
12722정성태7/20/20217189오류 유형: 739. MSVCR110.dll이 없어 exe 실행이 안 되는 경우
12721정성태7/20/20217843오류 유형: 738. The trust relationship between this workstation and the primary domain failed. - 세 번째 이야기
12720정성태7/19/20217178Linux: 43. .NET Core/5+ 응용 프로그램의 Ubuntu (Debian) 패키지 준비
12719정성태7/19/20216327오류 유형: 737. SharePoint 설치 시 "0x800710D8 The object identifier does not represent a valid object." 오류 발생
12718정성태7/19/20216892개발 환경 구성: 581. Windows에서 WSL로 파일 복사 시 root 소유권으로 적용되는 문제파일 다운로드1
12717정성태7/18/20216857Windows: 195. robocopy에서 파일의 ADS(Alternate Data Stream) 정보 복사를 제외하는 방법
12716정성태7/17/20217694개발 환경 구성: 580. msbuild의 Exec Task에 robocopy를 사용하는 방법파일 다운로드1
12715정성태7/17/20219375오류 유형: 736. Windows - MySQL zip 파일 버전의 "mysqld --skip-grant-tables" 실행 시 비정상 종료 [1]
12714정성태7/16/20218143오류 유형: 735. VCRUNTIME140.dll, MSVCP140.dll, VCRUNTIME140.dll, VCRUNTIME140_1.dll이 없어 exe 실행이 안 되는 경우
12713정성태7/16/20218697.NET Framework: 1077. C# - 동기 방식이면서 비동기 규약을 따르게 만드는 Task.FromResult파일 다운로드1
12712정성태7/15/20218100개발 환경 구성: 579. Azure - 리눅스 호스팅의 Site Extension 제작 방법
12711정성태7/15/20218437개발 환경 구성: 578. Azure - Java Web App Service를 위한 Site Extension 제작 방법
12710정성태7/15/202110260개발 환경 구성: 577. MQTT - emqx.io 서비스 소개
12709정성태7/14/20216884Linux: 42. 실행 중인 docker 컨테이너에 대한 구동 시점의 docker run 명령어를 확인하는 방법
12708정성태7/14/202110268Linux: 41. 리눅스 환경에서 디스크 용량 부족 시 원인 분석 방법
12707정성태7/14/202177503오류 유형: 734. MySQL - Authentication method 'caching_sha2_password' not supported by any of the available plugins.
12706정성태7/14/20218726.NET Framework: 1076. C# - AsyncLocal 기능을 CallContext만으로 구현하는 방법 [2]파일 다운로드1
12705정성태7/13/20218873VS.NET IDE: 168. x64 DLL 프로젝트의 컨트롤이 Visual Studio의 Designer에서 보이지 않는 문제 - 두 번째 이야기
... 31  32  33  34  35  [36]  37  38  39  40  41  42  43  44  45  ...