2008-09-27 21 views

Respuesta

11

Aquí hay algunos enlaces en (o relacionados con) este tema:

Lo que parece recordar de otro post en el blog de Robert Pickering (o era de Scott Hanselman?) Que, al final, porque ambos están sentados en el mismo marco, usted puede obtener el mismo rendimiento de ambos, pero a veces tiene que 'torcer' la expresión natural del idioma para hacerlo. En el ejemplo que recuerdo, tuvo que girar F # para obtener un rendimiento comparable con C# ...

+4

Lo contrario también es cierto si se beneficia de características exclusivas de F #, como 'en línea '. –

46

El código natural F # (por ejemplo, funcional/inmutable) es más lento que el código C# natural (imperativo/mutable orientado a objetos). Sin embargo, este tipo de F # es mucho más corto que el código C# habitual. Obviamente, hay una compensación.

Por otro lado, puede, en la mayoría de los casos, lograr el rendimiento del código F # igual al rendimiento del código C#. Por lo general, esto requerirá la codificación en estilo imperativo o mutable orientado a objetos, el perfil y eliminar los cuellos de botella. Utiliza las mismas herramientas que utilizaría en C#: p. Ej. .Net reflector y un perfilador.

Dicho esto, vale la pena tener en cuenta algunas construcciones de alta productividad en F # que disminuyen el rendimiento. En mi experiencia he visto los siguientes casos:

  • referencias (frente a las variables de instancia de clase), sólo en código ejecutado mil millones de veces

  • F # de comparación (= <) vs. System.Collections. Generic.Comparer, por ejemplo, en búsqueda binaria u ordenar

  • llamadas de cola - solo en ciertos casos que no pueden ser optimizados por el compilador o el tiempo de ejecución .Net. Como se señala en los comentarios, depende del tiempo de ejecución de .Net.

  • Las secuencias F # son dos veces más lentas que LINQ. Esto se debe a las referencias y al uso de funciones en la biblioteca F # para implementar la traducción de la secuencia < _>. Esto es fácilmente reparable, ya que puede reemplazar el módulo Seq por uno con las mismas firmas que usa Linq, PLinq o DryadLinq.

  • Tuples, F # tuple es una clase ordenada en el montón. En algunos casos, p. a int * int tuple podría serle útil usar una estructura.

  • Distribuciones, vale la pena recordar que un cierre es una clase creada con el nuevo operador, que recuerda las variables accedidas. Podría valer la pena "levantar" el cierre o reemplazarlo con una función que tome explícitamente las variables accedidas como argumentos.

  • Pruebe usar en línea para mejorar el rendimiento, especialmente para el código genérico.

Mi experiencia consiste en codificar primero en F # y optimizar solo las partes importantes. En ciertos casos, podría ser más fácil escribir las funciones lentas en C# en lugar de intentar ajustar F #. Sin embargo, desde el punto de vista de la eficiencia del programador, tiene sentido comenzar/prototipar en F #, luego perfilar, desmontar y optimizar.

En pocas palabras, su código F # podría terminar más lento que C# debido a las decisiones de diseño del programa, pero en última instancia puede obtenerse la eficiencia.

+2

Puntos interesantes, pero necesitaría verificar más de un solo tiempo de ejecución; con CLI 2, x86 y x64 tenían una cola muy diferente; obviamente se ha reforzado en parte debido al soporte de F #, pero esto puede sesgar los perfiles de C#. –

+9

"Esto generalmente requerirá codificación en estilo orientado a objetos imperativo o mutable". No, quieres una mutación para el rendimiento, pero debes * evitar * el estilo orientado a objetos a favor del estilo Fortran. OOP también es lento ... –

+1

Si realmente necesitan velocidad, creo que deberían considerar el lenguaje ensamblador sobre cualquier cosa. –

Cuestiones relacionadas