저는 Mesh Rendering 관리자를 작성 중이며 동일한 셰이더를 사용하는 모든 메시를 그룹화 한 다음 셰이더 패스에있는 동안이를 렌더링하는 것이 좋습니다.
현재 foreach
루프를 사용하고 있지만 LINQ를 사용하면 성능이 향상 될 수 있는지 궁금하십니까?
저는 Mesh Rendering 관리자를 작성 중이며 동일한 셰이더를 사용하는 모든 메시를 그룹화 한 다음 셰이더 패스에있는 동안이를 렌더링하는 것이 좋습니다.
현재 foreach
루프를 사용하고 있지만 LINQ를 사용하면 성능이 향상 될 수 있는지 궁금하십니까?
답변:
LINQ가 더 빨라야하는 이유는 무엇입니까? 또한 내부적으로 루프를 사용합니다.
대부분의 경우 LINQ는 오버 헤드를 유발하기 때문에 약간 느립니다. 성능에 관심이 많으면 LINQ를 사용하지 마십시오. 더 짧고 읽기 쉽고 유지 관리가 쉬운 코드를 원하기 때문에 LINQ를 사용하십시오.
LINQ-to-Objects는 일반적으로 약간의 한계 오버 헤드 (다중 반복기 등)를 추가합니다. 아직 루프를 수행하는, 그리고 위임 원용을 가지고, 그리고 일반적으로는 거의 발견 할 수없는 것입니다 대부분의 코드에서 촬영 된 변수 등을 얻을 수있는 몇 가지 여분의 역 참조를해야 할 것이며, 더 이상의 코드를 이해하기 위해 간단한에 의해 제공.
LINQ-to-SQL과 같은 다른 LINQ 공급자를 사용하면 쿼리가 서버에서 필터링 할 수 있으므로 flat보다 훨씬 낫지 만 어쨌든foreach
블랭킷을 수행하지 않았을 가능성이 높 으므로 반드시 공정 하지는 않습니다 . 비교."select * from foo"
Re PLINQ; 병렬 처리는 경과 시간을 줄일 수 있지만 일반적으로 총 CPU 시간은 스레드 관리 오버 헤드 등으로 인해 약간 증가합니다.
List<Foo>
. 대신 foreach
이러한 컬렉션에 블록을 사용해야합니다 . foreach
이러한 컨텍스트에서 사용하는 권장 사항 은 의미가 있습니다. 내 관심사 : LINQ 쿼리를foreach
성능 문제를 감지 한 경우 합니까? 앞으로는 foreach
첫 번째 를 고려할 것 입니다.
LINQ는 foreach
훨씬 깔끔하고 이해하기 쉬운 코드를 제공하기 때문에 루프를 통해 사용하는 것이 더 낫다고 생각 합니다. 그러나 LINQ는 foreach
. 자세한 내용은 LINQ vs FOREACH vs FOR Loop Performance 기사를 참조하십시오 .
LINQ는 현재 더 느리지 만 어느 시점에서는 더 빨라질 수 있습니다. LINQ의 좋은 점은 작동 방식에 신경 쓸 필요가 없다는 것입니다. 엄청나게 빠른 새로운 방법이 생각되면 Microsoft 직원은 사용자에게 말하지 않고도 구현할 수 있으며 코드가 훨씬 빨라질 것입니다.
하지만 더 중요한 것은 LINQ가 훨씬 읽기 쉽다는 것입니다. 충분한 이유가되어야합니다.
아마도 주목해야한다 for
루프가 빠르게보다 foreach
. 따라서 원본 게시물의 경우 렌더러와 같은 중요한 구성 요소의 성능이 걱정된다면 for
루프를 사용하십시오 .
다중 코어에 병렬 LINQ를 사용하면 성능이 향상 될 수 있습니다. 병렬 LINQ (PLINQ) (MSDN)를 참조하십시오 .
이 질문에 관심이있어서 방금 테스트를했습니다. .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=184 Exists=True Time=135
그것은 아파치 게임 노트북의 (윈 10, C # 7.3). 디버그 모드에서 컴파일 및 실행되었습니다. 테스트를 반대로하면 Exists=True Time=158 Exists=True Time=194
. Linq가 더 최적화 된 것 같습니다.
이것은 실제로 꽤 복잡한 질문입니다. Linq는 특정 작업을 매우 쉽게 수행 할 수 있으므로 직접 구현하면 실수 할 수 있습니다 (예 : linq .Except ()). 이는 특히 PLinq, 특히 PLinq에 의해 구현 된 병렬 집계에 적용됩니다.
일반적으로 동일한 코드의 경우 델리게이트 호출의 오버 헤드로 인해 linq가 느려집니다.
그러나 대규모 데이터 배열을 처리하고 요소에 비교적 간단한 계산을 적용하면 다음과 같은 경우 성능이 크게 향상됩니다.
for 루프를 사용하여 각 요소에 액세스합니다 (foreach 또는 linq와 반대).