Pregunta

He observado una gran cantidad de código "pila-introspectiva" de aplicaciones, que a menudo implícitamente dependen de sus métodos que contienen no se inline para su corrección. Tales métodos implican comúnmente llamadas a:

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

Ahora, encontrar la información que rodea a estos métodos a ser muy confuso. He oído decir que el tiempo de ejecución no inline un método que llama GetCurrentMethod, pero no puedo encontrar ninguna documentación a tal efecto. He visto puestos en StackOverflow en varias ocasiones, como éste , indicando el CLR no coloca en línea llamadas de montaje transversal, pero el GetCallingAssembly documentación indica claramente lo contrario.

También existe la [MethodImpl(MethodImplOptions.NoInlining)] tan denostada, pero no estoy seguro si el CLR considera que esto es una "solicitud" o un "comando".

Tenga en cuenta que estoy preguntando por inlining elegibilidad desde el punto de vista del contrato, no acerca de cuándo las implementaciones actuales de la disminución de jitter a considerar métodos a causa de las dificultades de aplicación, o sobre cuando el jitter finalmente termina por seleccionando para Inline un método elegible después de evaluar las ventajas y desventajas. He leído este y esta , pero parecen estar más centrado en los dos últimos puntos (no están pasando menciones de MethodImpOptions.NoInlining y "instrucciones IL exóticos", pero estos parecen ser presentado como heurística, más que como obligaciones ).

Cuando es el CLR permitido a inline?

¿Fue útil?

Solución

Es un detalle de implementación de jitter, la x86 y x64 nerviosismo tener sutilmente diferentes reglas. Esto es casualmente documentado en publicaciones en el blog de los miembros del equipo que trabajaron en la fluctuación, pero sin duda los equipos se reservan el derecho de alterar las reglas. Parece que ya las encontraron.

métodos de procesos en línea de otras asambleas es sin duda el apoyo, muchas de las clases .NET funcionaría bastante miserablemente si ese no era el caso. Se puede ver en el trabajo cuando nos fijamos en el código de máquina generado para Console.WriteLine (), que a menudo se inlined cuando se pasa una cadena sencilla. Para ver esto por sí mismo, es necesario cambiar a la versión de lanzamiento y cambiar una opción de depurador. Herramientas + Opciones, depuración, General, desmarca "reprimir optimización JIT en la carga del módulo".

En caso contrario hay ninguna buena razón para considerar MethodImpOptions.NoInlining calumniado, es más o menos por qué existe en el primer lugar. De hecho, es utilizado deliberadamente en el marco .NET en un montón de pequeños métodos públicos que llaman a un método de ayuda interna. Se hace seguimientos de pila excepción más fácil de diagnosticar.

Otros consejos

La respuesta de Hans Passant no obstante, aquí por primera vez un par de consejos a partir de 2004, y más abajo un poco más de información actualizada. Están sujetos a cambio, pero sí le dan una idea de lo que debe buscar si desea hacer una elegibles método para inlining:

el JIT no en línea:

  • Los métodos marcados con MethodImplOptions.NoInlining
  • Métodos mayor que 32 bytes de IL
  • métodos virtuales
  • métodos que tengan un gran tipo de valor como un parámetro
  • métodos en clases MarshalByRef
  • Métodos con flowgraphs complicados
  • Métodos cumplir otros criterios más exóticos

En particular, no se MethodImplOptions.AggressiveInlining , que se supone para levantar el límite de 32 bytes (o lo que pasa a ser en estos días y para su plataforma).

NET 3.5 heurística añadidos que ayuda que determinan si para integrado o no en línea , que es probablemente una cosa buena, a pesar de que hace más difícil para el desarrollador para predecir la decisión de la fluctuación:

Una cita del artículo:

  1. Si el código marcas procesos en línea más pequeña que la llamada al que sustituye, siempre es buena. Tenga en cuenta que estamos hablando del tamaño de código nativo, no se el tamaño del código IL (que puede ser muy diferente).

  2. Cuanto más un sitio de llamada particular se ejecuta, más se va a beneficiar de inlning. Así código en bucles merece ser más inline de código que no está en bucles.

  3. Si inlining expone optimizaciones importantes, entonces inlining es más deseable. En los métodos particulares con los tipos de valor argumentos beneficiarse más de lo normal debido a las optimizaciones de este tipo y por lo tanto que tiene un sesgo a inline estos métodos es buena.

Así, el heurísticos los usos del compilador JIT es X86, dada una inline candidato.

  1. Estimación del tamaño del sitio llamada si el método no eran inline.

  2. Estimación del tamaño del sitio llamada si se inline (esto es una estimación basada en la IL, empleamos una máquina de estados simples (Markov Modelo), creado con una gran cantidad de datos reales para formar esta lógica estimador)

  3. Calcular un multiplicador. Por defecto es 1

  4. Aumentar el multiplicador si el código está en un bucle (la heurística actual choca a 5 en un bucle)

  5. Aumentar el multiplicador si se ve como optimizaciones struct entrará en funcionamiento.

  6. Si InlineSize <= NonInlineSize * Multiplicador de hacer la expansión en línea.

Hans' contestar es correcta, hay una omisión, no necesariamente sobre cuando un método es elegible para la inclusión entre líneas, pero cuando un método es no .

abstracta y métodos virtuales no son elegibles para la inclusión entre líneas en el CLR .

Es importante tener en cuenta, ya que disminuye las establecen las condiciones bajo las cuales puede ser inline un método.

No hay más información sobre inlining de MethodBase.GetCurrentMethod en este hilo http: //prdlxvm0001.codify.net/pipermail/ozdotnet/2011-March/009085.html

Parafraseando en gran medida, se establece que el RefCrawlMark no detiene el método de llamada se inline. Sin embargo, RequireSecObject tiene el efecto lateral de detener la persona que llama se inline.

Además, los métodos y Assembly.GetCallingAssembly Assembly.GetExecutingAssembly no tienen este atributo.

Hubo un artículo publicado en MSDN en 2003 llamado escritura de alto rendimiento Gestionado Aplicaciones que cubre los contornos varios criterios bastante claridad:

  • Métodos que son mayores que 32 bytes de IL no ser inline.
  • funciones virtuales no están entre líneas.
  • métodos que tienen control de flujo complejo no estará en-forrado. control de flujo Complex es cualquier control de flujo distinta de si / entonces / else; en este caso, interruptor o tiempo.
  • Métodos que contienen bloques de manejo de excepciones no están entre líneas, aunque los métodos que generen excepciones siguen siendo candidatos para la inclusión entre líneas.
  • Si alguno de los argumentos formales del método son estructuras, no se inlined el método.

artículo del blog de Sacha Goldshtein en 2012 en inline agresivo en el CLR tiene gran parte del mismo consejo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top