इस नेस्टेड LINQ क्वेरी पर C # कंपाइलर क्यों पागल हो जाता है?


97

निम्नलिखित कोड को संकलित करने का प्रयास करें और आप पाएंगे कि कंपाइलर> 3 जीबी रैम (मेरी मशीन पर सभी मुफ्त मेमोरी) लेता है और संकलन करने के लिए बहुत लंबा समय (वास्तव में मुझे 10 मिनट के बाद आईओ अपवाद मिलता है)।

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) विज़ुअल C # संकलक संस्करण 4.0.30319.17929
OS नाम: माइक्रोसॉफ्ट विंडोज 7 अल्टीमेट
OS संस्करण: 6.1.7601 सर्विस पैक 1 बिल्ड 7601

स्मृति उपयोग


5
अच्छा निर्णय! मैंने अभी कोड को विज़ुअल स्टूडियो में पेस्ट किया है और यह सभी 4Gb का उपभोग करता है कि 32-बिट प्रक्रिया को अनुमति दी जाती है और फिर क्रैश हो जाता है (2013 विंडोज 8.1 पर अंतिम)।
५३ पर

2
इस कोड को एक साझा कोड-बेस (नोटपैड का उपयोग करके) में जोड़ें और अपने सह-कर्मचारियों की मशीनों को क्रैश देखें।
usr

3
Microsoft कनेक्ट पर रिपोर्ट करने के लिए एक अच्छी बात की तरह लगता है, और Roslyn टीम के लिए अगर उनके संकलक एक ही व्यवहार प्रदर्शित करता है।
ट्रिलियन

3
मेरा मानना ​​है कि मैंने एरिक लिपर्ट को कहीं न कहीं कहते सुना है (हालाँकि मुझे याद नहीं है कि कहाँ है) कि घोंसले के शिकार वाले लैम्ब्डा भी कई बार टाइपिंग के कारण कंपाइलर को खराब कर देते हैं। मैं नहीं सोच सकता कि मैंने इसे कहाँ देखा है, हालांकि यह एक संदर्भ का हवाला नहीं दे सकता है। उम्मीद है कि आदमी खुद इसे देख सकता है और टिप्पणी कर सकता है ...
क्रिस

2
अच्छा किया, इसे नीचे ट्रिम करें और आपके पास इसके लिए एक अच्छा जवाब हो सकता है: अपने पसंदीदा संकलक को क्रैश करें
नाथन कूपर

जवाबों:


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;
}

मेरा मानना ​​है कि एरिक लिपर्ट ने उस प्रकार से पहले पोस्ट किया है कि सी # कंपाइलर में एक जगह ऐसी है जहां (कुछ समस्याएं) कंपाइलर को एनपी-कम्प्लीट प्रॉब्लम को हल करने की कोशिश करने पर मजबूर कर सकती है और इसकी एकमात्र वास्तविक रणनीति (जैसा कि यहां है) ब्रूट फोर्स है। यदि मैं प्रासंगिक संदर्भ पा सकता हूं, तो मैं उन्हें यहां जोड़ूंगा।


सबसे अच्छा संदर्भ जो मैं पा सकता हूं, वह यहां है जहां एरिक इस तथ्य पर चर्चा कर रहा है कि यह अधिभार संकल्प कार्य है जो वास्तविक लागत का कारण बनता है - याद रखें, Enumerable.Sum में 10 अधिभार हैं जो एक लैम्ब्डा / विधि को स्वीकार करते हैं।


1
तो, मूल रूप से, संकलक 10^nसंयोजनों के माध्यम से अपने तरीके से bruteforces (जहां nजंजीर विधियों की मात्रा है)। उचित लगता है (स्पष्टीकरण के रूप में, यह है)।
डार्कवेंडर

1
@DarkWanderer:that^numberofpossibletypes
लीपी

@Damien_The_Unbeliever, मैं आपकी सोच को समझता हूं, सीम वास्तव में उचित है (जिस तरह से कोड संकलन नहीं करता है )
यूजीन डी। गुबेनकोव

15
यहां आपका विश्लेषण सही है। प्रत्येक लैम्ब्डा दस संभावित अधिभार के एक कारक का परिचय देता है, और सभी संयोजनों की जांच होनी चाहिए। मैंने ऐसे कोड जोड़ने पर विचार किया, जब संयोजनों की संख्या बड़ी हो गई, लेकिन इसे लागू करना कभी समाप्त नहीं हुआ।
एरिक लिपर्ट

2
@EricLippert पुल अनुरोध के लिए समय! : डी
रोब एच।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.