2015-11-24 7 views
7

मैं बस सोच रहा था कि क्या एक साधारण स्थैतिक फ़ंक्शन का उपयोग कर रहा है? ऑपरेटर को समय संकलन के दौरान रेखांकित किया गया है। कोड का उपयोग करके एक मनमाना उदाहरण यहां दिया गया है।क्या विधियों का उपयोग कर रहे हैं?: जेआईटी संकलन के दौरान ऑपरेटर रेखांकित?

public static int Max(int value, int max) 
    { 
     return value > max ? max : value; 
    } 

निम्नलिखित में से कौन आईएल देता है:

Max: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldarg.1  
IL_0003: bgt.s  IL_0008 
IL_0005: ldarg.0  
IL_0006: br.s  IL_0009 
IL_0008: ldarg.1  
IL_0009: stloc.0  
IL_000A: br.s  IL_000C 
IL_000C: ldloc.0  
IL_000D: ret 

या सरल विकल्प inlined किया जाएगा?

Max: 
IL_0000: nop   
IL_0001: ldarg.0  
IL_0002: ldarg.1  
IL_0003: cgt   
IL_0005: stloc.0  
IL_0006: ldloc.0  
IL_0007: brfalse.s IL_000E 
IL_0009: nop   
IL_000A: ldarg.1  
IL_000B: stloc.1  
IL_000C: br.s  IL_0013 
IL_000E: nop   
IL_000F: ldarg.0  
IL_0010: stloc.1  
IL_0011: br.s  IL_0013 
IL_0013: ldloc.1  
IL_0014: ret 

::

 public static int Max(int value, int max) 
     { 
      if (value > max) 
      { 
       return max; 
      } 
      else 
      { 
       return value; 
      } 
     } 

यहाँ इसके लिए आईएल है ऑपरेटर जाहिरा तौर पर एक अधिक संक्षिप्त MSIL अगर विकल्प की तुलना में उत्पन्न करता है, लेकिन किसी को भी पता है कि JIT संकलन के दौरान होता है? क्या वे दोनों रेखांकित हैं? क्या उनमें से कोई भी रेखांकित है?

+3

"इनलाइन" क्या घबराना अनुकूलक एक * विधि * के साथ करता है पर लागू होने वाला एक शब्द है। ?: ऑपरेटर एक विधि नहीं है, इसके लिए मशीन कोड हमेशा "लाइन में" उत्पन्न होता है, यहां तक ​​कि गैर-अनुकूलित डीबग बिल्ड में भी। –

+1

आपकी अधिकतम विधि? निश्चित रूप से, यह बहुत छोटा है और कुछ भी ऐसा नहीं करता है जो अनुकूलक पसंद नहीं करता है। आपको अपने प्रश्न का शीर्षक ठीक करने की जरूरत है। –

+0

@ क्रिस्टिक मैं हंस से सहमत हूं, आप शीर्षक थोड़ा भ्रामक है। यह ऐसा लगता है कि आप यह पूछ रहे हैं कि '?:' ऑपरेटर खुद को '?:' युक्त विधियों के बजाय रेखांकित किया गया है, जो आपका वास्तविक प्रश्न है। –

उत्तर

6

हम कैसे पता लगा सकते हैं? आइए जेनरेट कोड पर नज़र डालें।

internal static class Program 
{ 
    public static int MaxA(int value, int max) 
    { 
     return value > max ? max : value; 
    } 

    public static int MaxB(int value, int max) 
    { 
     if (value > max) 
      return max; 
     else 
      return value; 
    } 

    [MethodImpl(MethodImplOptions.NoInlining)] 
    private static int TestA(int a, int b) 
    { 
     return MaxA(a, b); 
    } 

    [MethodImpl(MethodImplOptions.NoInlining)] 
    private static int TestB(int a, int b) 
    { 
     return MaxB(a, b); 
    } 

    private static void Main() 
    { 
     var rand = new Random(); 
     var a = rand.Next(); 
     var b = rand.Next(); 

     var result = TestA(a, b); 
     Console.WriteLine(result); 

     result = TestB(a, b); 
     Console.WriteLine(result); 
    } 
} 

सबसे पहले, चलो कुछ चीजें सीधे मिलता है:

यहाँ एक परीक्षण कार्यक्रम है। एक रिलीज निर्माण में, MaxA के आईएल (रोसलिन पर) है:

.method public hidebysig static 
    int32 MaxA (
     int32 'value', 
     int32 max 
    ) cil managed 
{ 
    // Method begins at RVA 0x2050 
    // Code size 8 (0x8) 
    .maxstack 8 

    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: bgt.s IL_0006 

    IL_0004: ldarg.0 
    IL_0005: ret 

    IL_0006: ldarg.1 
    IL_0007: ret 
} // end of method Program::MaxA 

MaxB के लिए, यह है:

.method public hidebysig static 
    int32 MaxB (
     int32 'value', 
     int32 max 
    ) cil managed 
{ 
    // Method begins at RVA 0x2059 
    // Code size 8 (0x8) 
    .maxstack 8 

    IL_0000: ldarg.0 
    IL_0001: ldarg.1 
    IL_0002: ble.s IL_0006 

    IL_0004: ldarg.1 
    IL_0005: ret 

    IL_0006: ldarg.0 
    IL_0007: ret 
} // end of method Program::MaxB 

तो आईएल दोनों कार्य (यह एक ही कोड है के लिए सममित है, शाखाओं के आदेश के साथ-साथ शाखा निर्देश उलटा हुआ है)।

अब, चलो की जाँच क्या TestA और TestB के 64 कोड की तरह लग रहा करते हैं।

TestA, 64, RyuJIT:

  return MaxA(a, b); 
00007FFED5F94530 cmp   ecx,edx 
00007FFED5F94532 jg   00007FFED5F94538 
00007FFED5F94534 mov   eax,ecx 
00007FFED5F94536 jmp   00007FFED5F9453A 
00007FFED5F94538 mov   eax,edx 
00007FFED5F9453A ret 

आप देख सकते हैं कि MaxA समारोह inlined है (वहाँ कोई call अनुदेश है और आप स्पष्ट रूप से jg"कूद अगर अधिक से अधिक" शाखाओं में अनुदेश देख सकते हैं)।

TestB, 64:

  return MaxB(a, b); 
00007FFED5F94550 cmp   ecx,edx 
00007FFED5F94552 jle   00007FFED5F94558 
00007FFED5F94554 mov   eax,edx 
00007FFED5F94556 jmp   00007FFED5F9455A 
00007FFED5F94558 mov   eax,ecx 
00007FFED5F9455A ret 

इसमें कोई आश्चर्य नहीं कि हम एक ही परिणाम मिलता है।

compelteness के लिए, यहाँ MaxA 86 पर है:

  return MaxA(a, b); 
00A32E22 in   al,dx 
00A32E23 cmp   ecx,edx 
00A32E25 jg   00A32E2B 
00A32E27 mov   eax,ecx 
00A32E29 jmp   00A32E2D 
00A32E2B mov   eax,edx 
00A32E2D pop   ebp 
00A32E2E ret 

inlined रूप में अच्छी तरह।


संदर्भ के लिए, आप Disassembly खिड़की के साथ उत्पन्न विधानसभा कोड की जांच कर सकते (डीबग -> विंडोज -> Disassembly) जब आप एक ब्रेकप्वाइंट पर हैं, लेकिन पहले सुनिश्चित करें कि आप दबाने JIT सही का निशान बनाने पर मॉड्यूल लोड विकल्प अनुकूलन:

option to uncheck

3

टर्नरी ऑपरेटर के साथ एक विधि को रेखांकित किया जा सकता है। if/else के साथ एक विधि भी। बेशक यह सब विधि में अन्य परिचालनों पर निर्भर करता है।

इसे जांचने का एक आसान तरीका विधि में अपवाद फेंकना और स्टैक ट्रेस की जांच करना है। यदि विधि रेखांकित की गई थी, तो यह स्टैक ट्रेस में दिखाई नहीं देगी।

निम्नलिखित कोड

class Program 
{ 
    static void Main(string[] args) 
    { 
     try 
     { 
      int i = ThrowInTernaryOperator(1, 0); 
     } 
     catch (DivideByZeroException ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
    } 

    public static int ThrowInTernaryOperator(int value, int max) 
    { 
     return value > max ? value/0 : 0; 
    } 
} 
नेट 4.6 64-बिट (रिलीज निर्माण) में

निम्न अपवाद फेंकता है:

System.DivideByZeroException: शून्य से विभाजित करने का प्रयास किया।

Test.Program.Main पर

(स्ट्रिंग [] args)

स्टैक ट्रेस में कोई ThrowInTernaryOperator, तो यह inlined किया गया था।

व्यवहारकर्ता .NET और 32/64 बिट आर्किटेक्चर के विभिन्न संस्करणों में भिन्न हो सकता है।

संबंधित मुद्दे