Microsoft MVP성태의 닷넷 이야기
.NET Framework: 768. BenchmarkDotNet으로 Span<T> 성능 측정 [링크 복사], [링크+제목 복사]
조회: 13464
글쓴 사람
정성태 (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
정성태

... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13081정성태6/17/20226369.NET Framework: 2022. C# - .NET 7 Preview 5 신규 기능 - System.IO.Stream ReadExactly / ReadAtLeast파일 다운로드1
13080정성태6/17/20226990개발 환경 구성: 643. Visual Studio 2022 17.2 버전에서 C# 11 또는 .NET 7.0 preview 적용
13079정성태6/17/20224653오류 유형: 814. 파이썬 - Error: The file/path provided (...) does not appear to exist
13078정성태6/16/20226698.NET Framework: 2021. WPF - UI Thread와 Render Thread파일 다운로드1
13077정성태6/15/20227022스크립트: 40. 파이썬 - PostgreSQL 환경 구성
13075정성태6/15/20225988Linux: 50. Linux - apt와 apt-get의 차이 [2]
13074정성태6/13/20226301.NET Framework: 2020. C# - NTFS 파일에 사용자 정의 속성값 추가하는 방법파일 다운로드1
13073정성태6/12/20226527Windows: 207. Windows Server 2022에 도입된 WSL 2
13072정성태6/10/20226799Linux: 49. Linux - ls 명령어로 출력되는 디렉터리 색상 변경 방법
13071정성태6/9/20227378스크립트: 39. Python에서 cx_Oracle 환경 구성
13070정성태6/8/20227186오류 유형: 813. Windows 11에서 입력 포커스가 바뀌는 문제 [1]
13069정성태5/26/20229419.NET Framework: 2019. C# - .NET에서 제공하는 3가지 Timer 비교 [2]
13068정성태5/24/20227912.NET Framework: 2018. C# - 일정 크기를 할당하는 동안 GC를 (가능한) 멈추는 방법 [1]파일 다운로드1
13067정성태5/23/20227234Windows: 206. Outlook - 1년 이상 지난 메일이 기본적으로 안 보이는 문제
13066정성태5/23/20226560Windows: 205. Windows 11 - Windows + S(또는 Q)로 뜨는 작업 표시줄의 검색 바가 동작하지 않는 경우
13065정성태5/20/20227239.NET Framework: 2017. C# - Windows I/O Ring 소개 [2]파일 다운로드1
13064정성태5/18/20226767.NET Framework: 2016. C# - JIT 컴파일러의 인라인 메서드 처리 유무
13063정성태5/18/20227189.NET Framework: 2015. C# - 인라인 메서드(inline methods)
13062정성태5/17/20228008.NET Framework: 2014. C# - async/await 그리고 스레드 (4) 비동기 I/O 재현파일 다운로드1
13061정성태5/16/20226819.NET Framework: 2013. C# - FILE_FLAG_OVERLAPPED가 적용된 파일의 읽기/쓰기 시 Position 관리파일 다운로드1
13060정성태5/15/20229296.NET Framework: 2012. C# - async/await 그리고 스레드 (3) Task.Delay 재현파일 다운로드1
13059정성태5/14/20227745.NET Framework: 2011. C# - CLR ThreadPool의 I/O 스레드에 작업을 맡기는 방법 [1]파일 다운로드1
13058정성태5/13/20227654.NET Framework: 2010. C# - ThreadPool.SetMaxThreads 사용법
13057정성태5/12/20229334오류 유형: 812. 파이썬 - ImportError: cannot import name ...
13056정성태5/12/20226460.NET Framework: 2009. C# - async/await 그리고 스레드 (2) MyTask의 호출 흐름 [2]파일 다운로드1
13055정성태5/11/20229402.NET Framework: 2008. C# - async/await 그리고 스레드 (1) MyTask로 재현 [11]파일 다운로드1
... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...