Domanda

ho osservato un sacco di codice "stack-introspettiva" nelle applicazioni, che spesso implicitamente fanno affidamento sui loro metodi contenente non essere inline per la loro correttezza. Tali metodi comunemente coinvolgono le chiamate verso:

  • MethodBase.GetCurrentMethod
  • Assembly.GetCallingAssembly
  • Assembly.GetExecutingAssembly

Ora, trovo le informazioni che circonda questi metodi per essere molto confusa. Ho sentito dire che il runtime non inline un metodo che chiama GetCurrentMethod, ma non riesco a trovare alcuna documentazione in tal senso. Ho visto messaggi su StackOverflow in diverse occasioni, come ad esempio questo , che indica il CLR non in linea chiamate cross-assemblaggio, ma il GetCallingAssembly documentazione indica fortemente contrario.

C'è anche il tanto vituperato [MethodImpl(MethodImplOptions.NoInlining)], ma io sono sicuro se il CLR ritiene che questo sia una "richiesta" o un "comando."

Si noti che sto chiedendo circa inlining ammissibilità dal punto di vista contrattuale, non a quando le attuali implementazioni del declino jitter a prendere in considerazione metodi a causa delle difficoltà di attuazione, o circa quando il jitter finalmente finisce per scegliendo per INLINE un metodo idoneo dopo aver valutato il trade-off. Ho letto questo e questo , ma sembrano essere più concentrati sugli ultimi due punti (ci stanno passando menzioni di MethodImpOptions.NoInlining e "istruzioni IL esotiche", ma questi sembrano essere presentato come l'euristica piuttosto che come obblighi ).

Quando è il CLR permesso per inline?

È stato utile?

Soluzione

Si tratta di un dettaglio di implementazione jitter, x86 e x64 nervosismi avere regole leggermente diverse. Questo è casualmente documentato in post sul blog dei membri del team che hanno lavorato sul jitter ma le squadre certamente si riservano il diritto di modificare le regole. Sembra che già li ha trovati.

metodi inline da altre assemblee è certamente sostenuto, un sacco di classi .NET avrebbe funzionato abbastanza miseramente se non fosse il caso. Lo si può vedere al lavoro quando si guarda il codice macchina generato per Console.WriteLine (), spesso viene inline quando si passa una stringa semplice. Per vedere questo per te, è necessario passare alla costruzione di rilascio e modificare un'opzione debugger. Strumenti + Opzioni, debug, Generale, deselezionare "Ottimizzazione reprimere JIT del carico modulo".

Non v'è altro modo alcuna buona ragione per prendere in considerazione MethodImpOptions.NoInlining calunniato, è praticamente perché esiste in primo luogo. E 'infatti utilizzato intenzionalmente nel quadro di .NET su un sacco di piccoli metodi pubblici che chiamare un metodo di supporto interno. Rende stack eccezione più facili da diagnosticare.

Altri suggerimenti

La risposta di Hans Passant nonostante, qui prima un paio di suggerimenti come del 2004, e più in basso un po 'più aggiornate informazioni. Le tariffe sono soggette a cambiamenti, ma vi danno un'idea su cosa cercare, se si vuole fare un metodo idoneo per inlining:

  

JIT non sarà in linea:

     
      
  • I metodi contrassegnati con MethodImplOptions.NoInlining
  •   
  • I metodi più grandi di 32 byte di IL
  •   
  • metodi virtuali
  •   
  • metodi che accettano un ampio tipo di valore come parametro
  •   
  • I metodi di classi MarshalByRefObject
  •   
  • Metodi con flowgraphs complicate
  •   
  • Metodi incontrare altri criteri, più esotici
  •   

In particolare, si è MethodImplOptions.AggressiveInlining , che dovrebbe sollevare il limite di 32 byte (o quello che sembra essere in questi giorni e per la piattaforma).

.NET 3.5 euristica aggiunto che l'aiuto si determinano se per in linea o non in linea , che è probabilmente una buona cosa, anche se rende più difficile per lo sviluppatore di prevedere la decisione del jitter:

Una citazione dall'articolo:

  
      
  1. Se il codice rende inline più piccolo allora la chiamata che sostituisce, è sempre bene. Si noti che stiamo parlando delle dimensioni codice nativo, non   la dimensione del codice IL (che può essere molto differente).

  2.   
  3. Il più un particolare sito chiamata viene eseguito, tanto più potranno beneficiare di inlning. Così il codice in loop merita di essere inline più   di codice che non è in loop.

  4.   
  5. Se inlining espone le ottimizzazioni importanti, quindi inlining è più desiderabile. In particolare metodi i tipi valore argomenti   beneficiare di più del normale a causa di ottimizzazioni come questo e, quindi,   avente una polarizzazione all'inline questi metodi è buona.

  6.   
     

Così l'euristici gli usi del compilatore JIT è X86, dato un inline   candidato.

     
      
  1. Stima delle dimensioni del sito di chiamata se il metodo non sono stati inline.

  2.   
  3. Stima delle dimensioni del sito di chiamata se fosse inline (questa è una stima basata sulla IL, ci avvaliamo di una semplice macchina a stati (Markov   Model), creato con un sacco di dati reali per formare questa logica stimatore)

  4.   
  5. Calcola un moltiplicatore. Di default è 1

  6.   
  7. Aumentare il moltiplicatore se il codice è in un ciclo (l'euristica corrente urti a 5 in un ciclo)

  8.   
  9. Aumentare il moltiplicatore se sembra ottimizzazioni struct entreranno in gioco.

  10.   
  11. Se InlineSize <= NonInlineSize * Moltiplicatore fanno la messa in linea.

  12.   

Hans' rispondere a è corretto, c'è un'omissione, non necessariamente a quando un metodo è idoneo per inlining, ma quando un metodo è non .

astratta e metodi virtuali non sono ammissibili per inlining nel CLR .

E 'importante notare come whittles le condizioni alle quali un metodo di possono essere inline.

C'è più informazioni su inlining di MethodBase.GetCurrentMethod su questo thread http: //prdlxvm0001.codify.net/pipermail/ozdotnet/2011-March/009085.html

Parafrasando pesantemente, si afferma che la RefCrawlMark non si ferma il metodo chiamante viene inline. Tuttavia, RequireSecObject ha il lato effetto di fermare il chiamante viene inline.

In aggiunta, i metodi e Assembly.GetCallingAssembly Assembly.GetExecutingAssembly non hanno questo attributo.

C'è stato un articolo pubblicato su MSDN nel 2003 chiamato la scrittura ad alte prestazioni Managed Apps che copre le contorni diversi criteri chiaramente:

  • I metodi che sono maggiori di 32 byte di IL non sarà inline.
  • funzioni virtuali non sono inline.
  • I metodi che hanno il controllo del flusso complessa non sarà in-foderato. controllo di flusso complesso è alcun controllo di flusso diversa if / then / else; in questo caso, l'interruttore o mentre.
  • I metodi che contengono blocchi di gestione delle eccezioni non sono inline, anche se i metodi che gettano le eccezioni sono ancora candidati per inlining.
  • Se uno qualsiasi degli argomenti formali del metodo sono le strutture, non sarà inline il metodo.

articolo di blog di Sacha Goldshtein nel 2012 su inlining aggressiva nel CLR ha molto dello stesso consiglio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top