haskell - puedo - ¿Debo molestarme con los pragmas INLINE/INLINABLE para pequeñas funciones exportadas o GHC lo hará por mí?
porque cuando me enojo no me puedo controlar (2)
Desde mi experiencia, tales funciones pequeñas se integrarán automáticamente y en los bordes de los módulos, si tiene sentido.
Puede verificar si GHC decidió hacerlo posible, ejecutando ghc --show-iface
en el .hi
resultante. Si dice algo sobre un Unfolding
como en el siguiente ejemplo, al usar este módulo, la función probablemente estará en línea:
$ ghc --show-iface /usr/lib/ghc/base-4.6.0.1/Data/Either.hi
Magic: Wanted 33214052,
got 33214052
...
38da29044ff77a85b08cebca1fed11ad
either :: forall a c b.
(a -> c) -> (b -> c) -> Data.Either.Either a b -> c
{- Arity: 3, HasNoCafRefs, Strictness: LLS,
Unfolding: (/ @ a
@ c
@ b
f :: a -> c
ds :: b -> c
ds1 :: Data.Either.Either a b ->
case ds1 of wild {
Data.Either.Left x -> f x Data.Either.Right y -> ds y }) -}
Tengo un módulo que recopila y exporta un montón de funciones pequeñas como:
fromEither :: (MonadError e m) => Either e a -> m a
fromEither = either throwError return
o
withError :: MonadError e m => (e -> e) -> m a -> m a
withError = flip catchError (throwError . f)
Es una buena idea tenerlos en línea, ya que después de especializarse en una instancia particular de MonadError
es probable que se optimice una gran cantidad de código.
La documentación de GHC dice:
GHC (con
-O
, como siempre) intenta en línea (o "desplegar") funciones / valores que son "suficientemente pequeños", evitando así la sobrecarga de llamadas y posiblemente exponiendo otras optimizaciones más maravillosas. Normalmente, si GHC decide que una función es "demasiado costosa" para la línea, no lo hará, ni exportará ese despliegue para que otros módulos lo utilicen.
¿Significa que es más probable que estas funciones se traten como si tuvieran un pragma INLINE
(es decir, su RHS no optimizado registrado en el archivo de interfaz)? ¿O tengo que agregar INLINE
yo mismo? ¿Añadir algo cambia (suponiendo que GHC decida que son "lo suficientemente pequeños")?
No me importa si GHC decide no incluir algunas de mis funciones, si cree que son demasiado caras, pero en general me gustaría que estuvieran en línea sin contaminar mi código fuente y agregar INLINE
todas partes.
Quiero agregar a la respuesta de Joachim que el número de funciones en el módulo también influye en si ghc
exportará o no. Por ejemplo, Pipes.Prelude
from pipes
mostraría ralentizaciones en varias funciones cuando comencé a agregar varias funciones no relacionadas al mismo módulo. Agregar INLINABLE
INLINABLES a estas funciones restauró su velocidad original.