Linq에서 가장 기초가 되는 Where 문부터 시작하겠습니다.

참고 : https://learn.microsoft.com/ko-kr/dotnet/csharp/programming-guide/concepts/linq/filtering-data

 

 

필터링 메소드란?

필터링은 지정된 조건을 충족하는 요소만 포함하도록 결과 집합을 제한하는 작업을 가리킵니다.  라고 공식문서에서 말하네요.

그냥 간단하게 말해서 조건에 만족하는 요소만 추출해낸다.

예를 들어, 키가 180 이상인 사람만 고른다.  과일 중 귤만 고른다.

 

이런 필터링 메소드에 포함되는 Linq 메소드가 Where, OfType 이 있더군요.

Where은 정말 자주 사용하는데, OfType은 처음 알았네요. 사실 Where절이 워낙 범용적이라, Where로도 OfType은 대신할 수 있을거 같습니다만.... 성능면에서는 어떨지는 OfType에서 한 번 테스트해봐야겠네요.

 

Where 절

실행 쿼리문 메소드
지연된 실행 where Where

사용예시

필터결과 = 집합.Where(item => 필터 조건절)

- 집합내의 아이템들을 모두 조건절로 비교해서 부합하는 것만 뽑아내는 겁니다.

 

예제 및 활용

가장 기본적인 예

        char[] chars = new char[] {'a','b','k','q','g'};
        var res = chars.Where(item => item == 'k');

 

chars 배열 중에 k를 찾아줘 라는 구문이죠

 

Where 절을 사용 안하고 foreach문을 쓰면 아래와 같아집니다.

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

 

linq가 훨씬 깔끔하죠? 

코드가 복잡해질 수록, 조건자가 복잡해질 수록 더더욱 깔끔해집니다.

 

당연하게도 조건절에는 얼마든지 if문에 넣을 수 있는 것들은 다 들어갈 수 있습니다

        var res = chars.Where(item => item == 'k' && item == 'q');

 

뭐 이런식으로 &&, ||도 얼마든지 사용 가능!

 

하지만! 밑에서도 PS로 설명하겠지만, Where절은 편의성은 올라가지만 성능면에서는 떨어지는 편입니다. 모든 Linq가 그렇겠지만 코드 가독성, 유지보수 측면에서는 쓰기좋지만, 최적화가 중요한 곳에서는 남용하지 않으시길 권장드립니다.

 

 

PS. 성능 비교해보기.

1. Where절과 Foreach - if 를 직접 비교하기.

 코드 :

    public void OnClick1()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        var res = chars.Where(item => item == 'k');

        sw.Stop();
        Debug.Log($"Linq Time : {sw.ElapsedMilliseconds}ms");
    }

    public void OnClick2()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

        sw.Stop();
        Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms");
    }

 

결과:

 

상세 프로파일링 결과:

 Linq:

 

 Foreach:

 

결론:

얼핏 보면... Linq가 0ms!? 대박 할 수도 있는데.... 이건 Where절이 실행이 안된겁니다.

이게 Linq 특유의 "지연된 실행" 입니다.

Where절만 써서는 실제로 실행되지 않아요. 담아만 두고, 어딘가에서 Count() 또는 Foreach 등에서 사용을 할 때 비로소 실행이 됩니다.

 

그럼 이번엔 Foreach에 담아서 실행이 되게 해보죠.

 

2. Where절 - Foreach 와 Foreach - if 를 비교하기.

코드 :

    public void OnClick1()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        var res = chars.Where(item => item == 'k');

        foreach (var item in res)
        {
        }

        sw.Stop();
        Debug.Log($"Linq Time : {sw.ElapsedMilliseconds}ms");

    }

    public void OnClick2()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();

        foreach (var item in chars)
        {
            if (item == 'k')
            {
            }
        }

        sw.Stop();
        Debug.Log($"foreach Time : {sw.ElapsedMilliseconds}ms");
    }

 

결과:

프로파일링 결과:

Linq:

 

Foreach:

 

결론:

Linq가 확 느려졌죠? Foreach에 넣으면서 실제로 Where절이 실행되었기 때문입니다.

같은 foreach로 돌린거니까, if문과 Where절의 비교라고 볼 수 있겠네요.

즉, 지연되었던 실행이 실행되면 Linq의 Where절은 Foreach - if 보다 40배가량 느리다 입니다.

(여러번 테스트해본 결과 평균적으로 40배정도의 데이터가 나왔습니다.)

 

- Count 함수로 Where 절을 실행시켜 테스트 했을 때는 10배가량 느렸던 결과를 보았습니다. 대략 10 ~ 40배 라고 생각해도 꽤 큰 성능 차이죠? 

 

 

최종 결론:

 - Linq의 Where 절은 "지연된 실행"으로 실제로 다른 함수에 의해 실행되기까지 실행되지 않는다.

 - Linq의 Where 절은 같은 로직의 Foreach - if문보다 대략 40배정도 느리다.

 - 편의성은 올라가지만 성능면에서는 떨어지기 때문에 최적화가 중요한 곳에서는 남용하지 않기를 권장드립니다.

  (성능 저하를 잡기위해 프로파일링을 해보면 Linq에서 잡히는 경우가 꽤나 많습니다)

 

 

 

 

테스트 환경

  • cpu - i5-11400F
  • gpu - GeForce RTX 3060
  • Unity 2021.3.13f1
  • VisualStudio 2022
Posted by 검은거북

블로그 이미지
프로그래밍 공부 요약 및 공부하며 발생한 궁금증과 해결과정을 포스팅합니다.
검은거북

공지사항

Yesterday
Today
Total

달력

 « |  » 2025.1
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

최근에 올라온 글

최근에 달린 댓글

글 보관함