2011-03-24 9 views
9

Cuando answering a question with a suggestion to use GADTs, surgieron algunas preguntas con respecto al rendimiento en los comentarios. La pregunta implicaba una clase de tipos PlotValue:Implicaciones de rendimiento del uso de GADT

class PlotValue a where 
    value :: a -> Double 

y mi respuesta sugirió el uso de un GADT Input:

data Input where 
    Input :: (PlotValue a, PlotValue b) => Maybe a -> Maybe b -> Input 

pero los detalles son, supongo, inmaterial.

Me pregunto acerca de dos aspectos de la prestación del servicio:

Tiempo: ¿Existen costes de ejecución efectuados por una coincidencia de patrón como

case x of 
    Input (Just a) (Just b) -> value a * value b 
    _ -> 0.0 

por encima de los costos normales correspondientes: Maybe ¿valores?

espacio: ¿Cuánto sobrecarga de almacenamiento tiene un valor de tipo Input de transporte? Supongo que contiene los dos diccionarios PlotValue para cada valor del tipo Input (¿un 'puntero' cada uno?), Lo que significa que un [Input] será mucho más ineficiente en términos de uso de memoria que usando (Just Double, Just Double) o, mejor aún, (# #Double, #Double #) - si almacena los resultados de value en una tupla normal o sin empaquetar.

Entonces, aunque me encanta la expresividad que los GADT me dan, nunca he pensado demasiado en los aspectos de rendimiento. ¿Alguien puede decirme más sobre esto (y cualquier otro costo oculto del que pueda no estar enterado)?

Respuesta

13

Creo que has conseguido los gastos generales. Para cada variable existencialmente calificada necesita los diccionarios correspondientes (puntero a). Esto requiere espacio y, lo que es peor, las llamadas al método van a ser lentas. El (*) en su ejemplo será una llamada de función indirecta, mientras que con el doble habría sido una operación primitiva.

+2

Sin embargo, una declaración similar es verdadera sobre OOP y objetos de clases no finales (cada objeto pasado en un método necesita un puntero a una tabla de método virtual o equivalente), y C++ o Java son de alto rendimiento suficiente para aplicaciones. Por supuesto, en ambos idiomas usaría elementos que no sean OO, como las matrices, para algunos aspectos del rendimiento. Comentario obvio, pero quería ponerlo en perspectiva. –

+2

Gracias por su respuesta, ¡confirmando mis sospechas! El '(*)' en la expresión de caso me parece que siempre se usa en el tipo 'Double -> Double -> Double', ya que el resultado de' value' es 'Double', aunque' value' will evaluado todo el tiempo y puede ser costoso (como analizar un 'String') por lo que aquí simplemente' Double's lo hará mucho mejor. – yatima2975

Cuestiones relacionadas