이 중첩 된 LINQ 쿼리에서 C # 컴파일러가 미친 이유는 무엇입니까?


97

다음 코드를 컴파일하면 컴파일러가 3GB 이상의 RAM (내 컴퓨터의 모든 여유 메모리)을 사용하고 컴파일하는 데 매우 오랜 시간이 걸립니다 (실제로 10 분 후에 IO 예외가 발생 함).

using System;
using System.Linq;

public class Test
{
    public static void Main()
    {
        Enumerable.Range(0, 1).Sum(a =>
        Enumerable.Range(0, 1).Sum(b =>
        Enumerable.Range(0, 1).Sum(c =>
        Enumerable.Range(0, 1).Sum(d =>
        Enumerable.Range(0, 1).Sum(e =>
        Enumerable.Range(0, 1).Sum(f =>
        Enumerable.Range(0, 1).Count(g => true)))))));
    }
}

아무도이 이상한 행동을 설명 할 수 있습니까?

CS 버전 : Microsoft (R) Visual C # 컴파일러 버전 4.0.30319.17929
OS 이름 : Microsoft Windows 7 Ultimate
OS 버전 : 6.1.7601 Service Pack 1 Build 7601

메모리 사용량


5
좋은 전화! 방금 코드를 Visual Studio에 붙여 넣었고 32 비트 프로세스가 허용 된 다음 충돌하는 모든 4Gb를 소비했습니다 (Windows 8.1의 2013 Ultimate).
satnhak 2014

2
이 코드를 공유 코드 기반 (메모장 사용)에 추가하고 동료 컴퓨터가 충돌하는 것을 지켜보십시오.
usr

3
Microsoft Connect에 대해보고하고 컴파일러가 동일한 동작을 보이는 경우 Roslyn 팀에보고하는 것이 좋은 것 같습니다.
Trillian 2014

3
나는 Eric Lippert가 어딘가에서 (내가 기억할 수는 없지만) 타입 추론으로 람다를 너무 자주 중첩하면 컴파일러가 불쾌한 골칫거리를 일으킬 수 있다고 말하는 것을 들었다고 생각합니다. 나는 그것을 어디에서 보았는지 생각할 수 없으므로 참조를 인용 할 수 없습니다. 바라건대 그 사람 자신은 ... 이것과 코멘트를 볼 수 있습니다
크리스

2
잘하셨습니다. 정리하면 이에 대한 좋은 답을 얻을 수 있습니다. 좋아하는 컴파일러 충돌
Nathan Cooper

답변:


40

유형 추론 및 / 또는 람다 생성 (유형 추론이 정상과 반대 방향으로 진행되어야하는 경우)과 관련이 있으며 과부하 해결과 관련이 있다고 생각합니다. 불행히도 유형 매개 변수를 제공하는 것만으로는 상황에 도움이되지 않습니다 (아마도 유형 검사를 수행해야하는 경우).

람다를 분석 한 후 논리적으로 동등한 코드 여야하는 다음 코드는 문제없이 컴파일됩니다.

static void Main()
{
    var x = Enumerable.Range(0, 1).Sum(a);
}

private static int a(int a)
{
    return Enumerable.Range(0, 1).Sum(b);
}
private static int b(int b)
{
    return Enumerable.Range(0, 1).Sum(c);
}
private static int c(int c)
{
    return Enumerable.Range(0, 1).Sum(d);
}
private static int d(int d)
{
    return Enumerable.Range(0, 1).Sum(e);
}
private static int e(int e)
{
    return Enumerable.Range(0, 1).Sum(f);
}
private static int f(int f)
{
    return Enumerable.Range(0, 1).Count(g);
}
private static bool g(int g)
{
    return true;
}

나는 Eric Lippert가 그 유형 추론이 C # 컴파일러에서 (특정 문제) 컴파일러가 NP-Complete 문제를 해결하도록 강제 할 수있는 장소 중 하나이며 유일한 실제 전략 (여기)이 무차별적인 힘이라는 것을 게시하기 전에 게시했다고 생각합니다. 관련 참조를 찾을 수 있으면 여기에 추가하겠습니다.


내가 찾을 수있는 가장 좋은 참조는 여기 에서 Eric이 실제 비용을 유발하는 과부하 해결 작업이라는 사실에 대해 논의하는 곳입니다. Enumerable을 기억하십시오. 에는 람다 / 메소드를 허용하는 10 개의 과부하가 있습니다.


1
따라서 기본적으로 컴파일러 는 10^n조합을 통해 자신의 방식을 무차별 적으로 수행합니다 ( n연결된 메서드의 양은 어디에 있습니까 ). 합리적으로 들립니다 (설명으로서).
DarkWanderer 2014

1
@DarkWanderer :that^numberofpossibletypes
leppie

@Damien_The_Unbeliever, 당신의 생각을 이해하고, 솔기 정말 합리적인 (그런데 코드는 컴파일되지 않습니다 )
유진 D. Gubenkov

15
여기의 분석이 정확합니다. 각 람다는 10 개의 가능한 과부하 요소를 도입하며 모든 조합을 확인해야합니다. 나는 조합의 수가 많아졌지만 결코 구현하지 못한 코드를 추가하는 것을 고려했습니다.
Eric Lippert 2014

2
@EricLippert 풀 리퀘스트 시간! : D
Rob H
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.