LINQ 문이 'foreach'루프보다 빠릅니까?


124

저는 Mesh Rendering 관리자를 작성 중이며 동일한 셰이더를 사용하는 모든 메시를 그룹화 한 다음 셰이더 패스에있는 동안이를 렌더링하는 것이 좋습니다.

현재 foreach루프를 사용하고 있지만 LINQ를 사용하면 성능이 향상 될 수 있는지 궁금하십니까?



1
허용되는 답변에 @MarcGravell의 답변을 설정하는 것을 고려하십시오. 예를 들어 linq가 for / foreach보다 빠른 경우 linq에서 sql 로의 상황이 있습니다.
paqogomez

답변:


222

LINQ가 더 빨라야하는 이유는 무엇입니까? 또한 내부적으로 루프를 사용합니다.

대부분의 경우 LINQ는 오버 헤드를 유발하기 때문에 약간 느립니다. 성능에 관심이 많으면 LINQ를 사용하지 마십시오. 더 짧고 읽기 쉽고 유지 관리가 쉬운 코드를 원하기 때문에 LINQ를 사용하십시오.


7
그렇다면 LINQ가 더 빠르고 코드를 읽고 유지하기가 더 어렵습니다. 설명 해주십시오.
codymanix 2011-06-27

87
나는 당신이 그것을 거꾸로 가지고 있다고 생각합니다. 그는 LINQ가 느리다고 말하고 있습니다. 이것은 오버 헤드 때문입니다. 그는 또한 LINQ가 읽기 및 유지 관리가 더 쉽다고 말합니다.
Joseph McIntyre 2013

5
죄송합니다. 그 동안 우리는 linq와 for 또는 foreach 성능을 비교 한 많은 것들을 가지고 있었고 대부분의 경우 linq가 더 빨랐습니다.
Offler

34
솔직히 말해서 foreach 루프는 LINQ 메서드보다 더 읽기 쉽습니다. 나는 LINQ가 멋지 기 때문에 사용합니다. :)
LuckyLikey

4
예,하지만 어떤 경우에는 LINQ가 가독성을 실제로 향상시킬 수 있으므로 내 생각없는 댓글은 잊어 버리십시오. <3
LuckyLikey

59

LINQ-to-Objects는 일반적으로 약간의 한계 오버 헤드 (다중 반복기 등)를 추가합니다. 아직 루프를 수행하는, 그리고 위임 원용을 가지고, 그리고 일반적으로는 거의 발견 할 수없는 것입니다 대부분의 코드에서 촬영 된 변수 등을 얻을 수있는 몇 가지 여분의 역 참조를해야 할 것이며, 더 이상의 코드를 이해하기 위해 간단한에 의해 제공.

LINQ-to-SQL과 같은 다른 LINQ 공급자를 사용하면 쿼리가 서버에서 필터링 할 수 있으므로 flat보다 훨씬 낫지어쨌든foreach 블랭킷을 수행하지 않았을 가능성이 높 으므로 반드시 공정 하지는 않습니다 . 비교."select * from foo"

Re PLINQ; 병렬 처리는 경과 시간을 줄일 수 있지만 일반적으로 총 CPU 시간은 스레드 관리 오버 헤드 등으로 인해 약간 증가합니다.


또 다른 답변 에서 메모리 내 컬렉션에서 LINQ를 사용 하지 않는다고 언급 했습니다 List<Foo>. 대신 foreach이러한 컬렉션에 블록을 사용해야합니다 . foreach이러한 컨텍스트에서 사용하는 권장 사항 은 의미가 있습니다. 내 관심사 : LINQ 쿼리를foreach 성능 문제를 감지 한 경우 합니까? 앞으로는 foreach첫 번째 를 고려할 것 입니다.
IAbstract 2015


15

LINQ는 현재 더 느리지 만 어느 시점에서는 더 빨라질 수 있습니다. LINQ의 좋은 점은 작동 방식에 신경 쓸 필요가 없다는 것입니다. 엄청나게 빠른 새로운 방법이 생각되면 Microsoft 직원은 사용자에게 말하지 않고도 구현할 수 있으며 코드가 훨씬 빨라질 것입니다.

하지만 더 중요한 것은 LINQ가 훨씬 읽기 쉽다는 것입니다. 충분한 이유가되어야합니다.


3
"Microsoft에서 구현할 수 있습니다."라는 문구가 마음에 듭니다. 프레임 워크를 업그레이드하지 않고도 가능합니까?
Shrivallabh

1
LINQ는 결국 네이티브 구현으로 변환되기 때문에 네이티브 구현보다 더 빠르지 않습니다. 더 빠른 LINQ 기계어 코드를 번역하는 데 사용할 수있는 특별한 LINQ CPU 명령어와 LINQ 레지스터는 없습니다.
mg30rg 2017

사실이 아닙니다. 어떤 지점에서는 특정 링크 작업이 다중 스레드가되거나 특정 지점에서 GPU를 활용할 수도 있습니다.
John Stock



5

이 질문에 관심이있어서 방금 테스트를했습니다. .NET Framework 4.5.2를 Intel (R) Core (TM) i3-2328M CPU @ 2.20GHz, 2200Mhz, 2 코어 (Microsoft Windows 7 Ultimate를 실행하는 8GB RAM)에서 사용.

LINQ가 각 루프보다 빠를 수 있습니다. 내가 얻은 결과는 다음과 같습니다.

Exists = True
Time   = 174
Exists = True
Time   = 149

여러분 중 일부가이 코드를 콘솔 앱에 복사하여 붙여넣고 테스트 할 수 있다면 흥미로울 것입니다. 객체 (Employee)로 테스트하기 전에 정수로 동일한 테스트를 시도했습니다. LINQ도 더 빨랐습니다.

public class Program
{
    public class Employee
    {
        public int id;
        public string name;
        public string lastname;
        public DateTime dateOfBirth;

        public Employee(int id,string name,string lastname,DateTime dateOfBirth)
        {
            this.id = id;
            this.name = name;
            this.lastname = lastname;
            this.dateOfBirth = dateOfBirth;

        }
    }

    public static void Main() => StartObjTest();

    #region object test

    public static void StartObjTest()
    {
        List<Employee> items = new List<Employee>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(new Employee(i,"name" + i,"lastname" + i,DateTime.Today));
        }

        Test3(items, items.Count-100);
        Test4(items, items.Count - 100);

        Console.Read();
    }


    public static void Test3(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item.id == idToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test4(List<Employee> items, int idToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Exists(e => e.id == idToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion


    #region int test
    public static void StartIntTest()
    {
        List<int> items = new List<int>();

        for (int i = 0; i < 10000000; i++)
        {
            items.Add(i);
        }

        Test1(items, -100);
        Test2(items, -100);

        Console.Read();
    }

    public static void Test1(List<int> items,int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = false;
        foreach (var item in items)
        {
            if (item == itemToCheck)
            {
                exists = true;
                break;
            }
        }

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    public static void Test2(List<int> items, int itemToCheck)
    {

        Stopwatch s = new Stopwatch();
        s.Start();

        bool exists = items.Contains(itemToCheck);

        Console.WriteLine("Exists=" + exists);
        Console.WriteLine("Time=" + s.ElapsedMilliseconds);

    }

    #endregion

}

이것이 내가 얻은 것입니다. Exists = True Time = 274 Exists = True Time = 314
PmanAce

2
linq를 먼저 수행하고 나중에 수행하는 것을 고려
했습니까

3
흥미 롭군. 내가 가지고 Exists=True Time=184 Exists=True Time=135그것은 아파치 게임 노트북의 (윈 10, C # 7.3). 디버그 모드에서 컴파일 및 실행되었습니다. 테스트를 반대로하면 Exists=True Time=158 Exists=True Time=194. Linq가 더 최적화 된 것 같습니다.
James Wilkins 19 년

1
이 게시물에는 개체 테스트와 관련하여 오해가 있습니다. List.Exists 및 .Contains가 foreach보다 더 나은 성능을 보이는 것이 확실히 흥미롭지 만. .Exists는 엔티티에 대한 linq 메소드가 아니며 목록에서만 작동합니다. linq에 해당하는 메소드 인 .Any ()는 foreach보다 확실히 느리게 수행됩니다.
AbdulG

3

이것은 실제로 꽤 복잡한 질문입니다. Linq는 특정 작업을 매우 쉽게 수행 할 수 있으므로 직접 구현하면 실수 할 수 있습니다 (예 : linq .Except ()). 이는 특히 PLinq, 특히 PLinq에 의해 구현 된 병렬 집계에 적용됩니다.

일반적으로 동일한 코드의 경우 델리게이트 호출의 오버 헤드로 인해 linq가 느려집니다.

그러나 대규모 데이터 배열을 처리하고 요소에 비교적 간단한 계산을 적용하면 다음과 같은 경우 성능이 크게 향상됩니다.

  1. 배열을 사용하여 데이터를 저장합니다.
  2. for 루프를 사용하여 각 요소에 액세스합니다 (foreach 또는 linq와 반대).

    • 참고 : 벤치마킹 할 때 모든 사람이 기억하십시오. 두 번의 연속 테스트에 동일한 어레이 / 목록을 사용하면 CPU 캐시가 두 번째 테스트를 더 빠르게 만듭니다. *
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.