2009-09-15 30 views
5

(Esto estaba destinado a ser una pregunta hipotética en general, me lloriqueando que .NET era un cerdo y pidiendo razones. No fue realmente destinado a ser una pregunta acerca de mi aplicación específica.)¿Por qué .NET usa tanta CPU, es esto un problema?

Actualmente estoy reescribiendo algún viejo código de C++ en C#. Estamos portando todas las aplicaciones heredadas. Tengo aplicaciones C++ que toman MAX 3% de CPU. En general, no usan ninguno. Luego tomo el código, copio y pego, luego vuelvo a formatear a sintaxis C# y bibliotecas .NET, ¡y BAM! 50% de CPU. ¿Cuál es la razón de esto? Al principio pensé que era JIT, pero incluso después de que cada ruta de código haya sido ejercicios, y todo ha sido JIT ed, el mismo problema.

También he notado un gran aumento de memoria. Las aplicaciones que tomaron 9 MB ejecutando una carga completa ahora comienzan en 10 MB y se ejecutan en 50 MB. Me doy cuenta de que el hardware es barato, pero quiero entender qué causa esto. ¿Es motivo de alarma, o es .NET tanto que el cerdo?

Actualización 1 respuesta a skeet

estoy familiarizado con C#. Cambio las cosas a Linq, y así sucesivamente. Por lo general, tomo el código y reduzco el número de líneas, y así sucesivamente. ¿Podría dar algunos ejemplos más de lo que hace una persona de C++ en .NET?

Actualización 2

Esto estaba destinado a ser una cuestión general, pero la aplicación específica que tiene el problema es el siguiente.

Tiene un hilo que utiliza y un controlador ODBC para obtener datos de una paradoja db. A continuación, utiliza Linq para transformarlo a SQL db y publicarlo. Lo he pasado por ANTS profiler, y parece que el llenado del conjunto de datos lleva más tiempo. Seguido por la publicación de Linq. Sé que algunas de mis áreas son el uso de la reflexión, pero no veo cómo hacer lo que necesito sin esto. Planeo cambiar mi cadena a constructores de cadenas. ¿Hay alguna diferencia entre estos dos?

(int)datarow["Index"] 

y

ConvertTo.Int32(datarow["Index"]) 

me cambió todo concatenación de cadenas a cadenas de formato. Eso no se redujo por encima de la cabeza. ¿Alguien sabe la diferencia entre un lector de datos vs adaptador de datos y conjuntos de datos?

+9

En lugar de necesitar ejemplos teóricos, puede que sea mejor usar un generador de perfiles para ver por qué/dónde está gastando su CPU la aplicación. – ChrisW

+1

Parece que puede ser la interacción con ODBC. ¿Hay un controlador .NET Paradox "nativo" disponible? –

+3

50% CPU por cuánto tiempo? Para que tarea? En mini-benchmarks intensivos en CPU que he estudiado, C++ fue más rápido que C#, pero no mucho. En cada caso, saturé la CPU para obtener el mayor rendimiento. – Cheeso

Respuesta

17

¿Qué tan familiar está con C# y .NET? Si solo transfieres el código heredado manteniendo las expresiones idiomáticas de C++, no estoy para nada sorprendido de que sea un cerdo. Portar aplicaciones textualmente de una plataforma a otra casi nunca es una buena idea. (Por supuesto, no has dicho que definitivamente has hecho eso). Además, si eres un desarrollador experto en C++ pero un desarrollador de .NET novato, deberías esperar que tu código realice como si fueras principiante en el plataforma.

No podemos decir realmente qué está llevando a cabo el rendimiento sin saber más acerca de la aplicación, aunque no me sorprendería saber que la concatenación de cadenas fue la culpable. ¿Cuántos procesadores tienes en la caja? Si es 2, entonces la aplicación básicamente está tomando todo lo que puede para un solo hilo ...

.NET generalmente será más pesado en términos de memoria que una aplicación C++, pero debería ser al menos comparable en términos de velocidad para la mayoría de las tareas. Tomar 50MB en lugar de 9MB suena como más de lo que esperaba, pero no estaría inmediatamente demasiado preocupado.

Tanto la memoria como el rendimiento de la CPU deben investigarse con un buen perfilador. Puedo recomendar JetBrains dotTrace Profiler, pero hay muchos otros por ahí.

+0

¿Podría dar algunos ejemplos más? –

+0

¿Le gustaría lo que sería una cosa .NET de principiante que un chico de C++ podría hacer? –

+3

Ejemplos de qué? Sin saber nada sobre su aplicación, sería * muy * difícil adivinar dónde podrían estar los cuellos de botella. Incluso el simple hecho de usar LINQ podría generar un cuello de botella si no tiene cuidado. Realmente iría por un perfilador, cualquier otra cosa solo será conjetura. –

0

Yo diría que el uso de la memoria probablemente esté en línea, pero el uso de la CPU no lo es.

Parece que tienes un hilo que no cede.

1

Debería ver un cierto aumento en el uso de la CPU. 3% a 50% suena demasiado, ¿qué tipo de código es este?

La huella de memoria es solo el costo ineludible. Cualquier cosa entre 30-50 MB para una aplicación .NET es normal. Normalmente, el uso real de memoria de su aplicación .NET es muy pequeño, pero hay una sobrecarga de tiempo de ejecución considerable que no puede evitar (este es un costo único, pero está allí) y es muy notable si hace referencia a toneladas de ensamblajes. .

0

puedo pensar en algunas conjeturas:

1) Memoria - C++ no han logrado memoria. Por lo tanto, libera la memoria de forma incremental y en (si se programa bien) tiempos óptimos.

Con la memoria administrada, el programa básicamente "filtrará" la memoria hasta el momento en que decida hacer la coilección de basura. El tiempo probablemente depende de la cantidad de memoria asignada al proceso. Probablemente haya una forma de cambiar el comportamiento predeterminado, pero un tamaño de memoria más pequeño significa que la recolección de basura se realiza antes y con mayor frecuencia, lo que afecta el tiempo de procesamiento. Si se asigna suficiente memoria, entonces puede que no sea necesario invocar gc.

2) ¿Se ejecuta el programa al mismo tiempo o menos? Si usa 5 veces más potencia de procesador pero completa en 1/5 del tiempo, entonces la CPU utilizada es básicamente equivalente.

3) Sí, .NET es probablemente un cerdo

+1

Si llama a .Net un cerdo, su nombre es muy apropiado –

+0

No lo entendí :) Personalmente, hoy no veo nada de malo en ser un "cerdo" .. Me gusta VB .NET, es el mejor entorno de programación Lo he tenido desde el interlisp a finales de los 80, y está respaldado por un marco que se puede usar para entregar aplicaciones comerciales en lugar de simples demostraciones/investigaciones/pruebas de concepto. Creo que la principal lección de Java fue "está bien ser un cerdo ahora ... tenemos suficiente poder de procesamiento" que Microsoft tomó en serio y reimplementó, en mi opinión, de una manera mucho mejor (mejor IDE, mejor código generado más eficiente) Es un cerdo pero un cerdo muy RÁPIDO :) –

6

yo sepa no hay diferencia entre litte (int)datarow["Index"] y ConvertTo.Int32(datarow["Index"]). Sin embargo hay una gran diferencia si se utiliza la corriente de datos en modo lectores:

int orderIndex = <order of Index column in projection list>; 
using (OdbcDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) 
{ 
    int Index = rdr.GetInt32(orderIndex); 
} 

El comportamiento del comando SeqentialAccess es la forma con mayor crecimiento para procesar los resultados de SQL, ya que elimina el almacenamiento en caché adicional necesario para el acceso aleatorio.

Un segundo aviso es que parece que está utilizando conjuntos de datos. Los conjuntos de datos son fáciles de usar, pero están muy lejos de lo que cualquiera puede llamar "rápido". Con los conjuntos de datos, básicamente está ejecutando un motor de almacenamiento en memoria (creo que se basa en Rushmore). Si desea exprimir cada ciclo de CPU y todos los 1s de cada bit de RAM, entonces tendrá que usar componentes más delgados (por ejemplo, matrices en bruto de estructuras en lugar de Datasets y DataTables).

Al comparar manzanas con manzanas, CLR puede mantener su posición frente al código nativo. El código IL se puede nativizar en el momento del despliegue con NGEN. Los costos indirectos de CLR típicos son bounds checks can be avoided. La 'pausa' de apropiación de GC ocurre solo si usted es descuidado con su asignación (solo porque tenga GC no significa que deba asignar izquierda y derecha). Y CLR en realidad tiene algunos ases en cuanto a la disposición de la memoria, ya que puede reagrupar el objeto en la memoria para ajustarse a los patrones de acceso y mejorar la localidad TLB y L2.

Por cierto, si crees que el debate 'C++ puede ejecutar círculos alrededor de C#' es algo nuevo, recuerdo un momento en que C podía correr círculos alrededor de C++ ('las llamadas virtuales son imposiblemente lentas' decían) y escuché era un ensamblado de tiempo que corría alrededor de C.

Cuestiones relacionadas