¿Cuánto más rápido es C ++ que C #?


245

¿O es ahora al revés?

Por lo que he escuchado, hay algunas áreas en las que C # demuestra ser más rápido que C ++, pero nunca he tenido las agallas para probarlo por mí mismo.

Pensé que alguno de ustedes podría explicar estas diferencias en detalle o señalarme el lugar correcto para obtener información al respecto.


77
Protegido, para evitar que se publiquen más puntos de referencia aleatorios. Si cree que puede presentar su caso, necesitará 10 representantes para hacerlo.
Robert Harvey

2
¿Cómo es que esto no se cierra como opinión / argumentativo de todos modos? ¿Todavía no estoy en StackOverflow? (No sugiero el cierre, solo curiosidad. Me encantan las preguntas que estimulan argumentos obstinados)
Bill K

1
Es casi una pregunta discutible, dado que vivimos en una época en la que IL se puede convertir a CPP y optimizar desde allí: docs.unity3d.com/Manual/IL2CPP.html
pixelpax

Un lenguaje que verifique el acceso a una matriz fuera de rango nunca superará a uno que no lo haga.
Seva Alekseyev

@SevaAlekseyev No es el lenguaje el que hace esto sino el compilador. Una de las razones por las que C ++ es tan rápido (aparte de los obvios) es que los compiladores de C ++ han existido durante los últimos 35 años (si no más). No hay nada que impida que los compiladores de C # mejoren con el tiempo. Para el caso que menciona, lea este stackoverflow.com/questions/16713076/…
Captura del

Respuestas:


342

No hay una razón estricta por la cual un lenguaje basado en bytecode como C # o Java que tiene un JIT no pueda ser tan rápido como el código C ++. Sin embargo, el código C ++ solía ser significativamente más rápido durante mucho tiempo, y hoy en día todavía lo es en muchos casos. Esto se debe principalmente a que las optimizaciones JIT más avanzadas son complicadas de implementar, y las realmente geniales solo están llegando en este momento.

Entonces C ++ es más rápido, en muchos casos. Pero esto es solo una parte de la respuesta. Los casos en que C ++ es en realidad más rápido son programas altamente optimizados, donde los programadores expertos optimizan a fondo el código. Esto no solo consume mucho tiempo (y, por lo tanto, es costoso), sino que también conduce a errores debido a una optimización excesiva.

Por otro lado, el código en lenguajes interpretados se acelera en versiones posteriores del tiempo de ejecución (.NET CLR o Java VM), sin que usted haga nada. Y hay muchas optimizaciones útiles que los compiladores JIT pueden hacer que son simplemente imposibles en idiomas con punteros. Además, algunos argumentan que la recolección de basura generalmente debe ser tan rápida o más rápida como la administración manual de memoria, y en muchos casos lo es. En general, puede implementar y lograr todo esto en C ++ o C, pero será mucho más complicado y propenso a errores.

Como dijo Donald Knuth, "la optimización prematura es la raíz de todo mal". Si realmente sabe con certeza que su aplicación consistirá principalmente en aritmética muy crítica de rendimiento, y que será el cuello de botella, y ciertamente será más rápido en C ++, y está seguro de que C ++ no entrará en conflicto con su otro requisitos, vaya para C ++. En cualquier otro caso, concéntrese primero en implementar su aplicación correctamente en el idioma que más le convenga, luego encuentre cuellos de botella de rendimiento si funciona demasiado lento y luego piense en cómo optimizar el código. En el peor de los casos, es posible que deba llamar al código C a través de una interfaz de función externa, por lo que aún tendrá la capacidad de escribir partes críticas en un lenguaje de nivel inferior.

Tenga en cuenta que es relativamente fácil optimizar un programa correcto, pero mucho más difícil corregir un programa optimizado.

Es imposible dar porcentajes reales de ventajas de velocidad, depende en gran medida de su código. En muchos casos, la implementación del lenguaje de programación ni siquiera es el cuello de botella. Tome los puntos de referencia en http://benchmarksgame.alioth.debian.org/ con mucho escepticismo, ya que estos prueban en gran medida el código aritmético, que probablemente no sea similar a su código.


92
El código <quote> en los idiomas interpretados se acelera en las versiones posteriores del tiempo de ejecución </quote> Como el código compilado por una versión mejor del compilador también será más rápido.
Martin York

47
De hecho, hay al menos una razón: JIT debe ser rápido y no puede permitirse perder tiempo en varias optimizaciones avanzadas disponibles para un compilador de C ++.
Nemanja Trifunovic

63
"pero también suele provocar errores debido a optimizaciones excesivas". [cita desesperadamente necesaria]. Trabajo en un laboratorio nacional y optimizamos nuestro código al máximo. Esto no suele generar código defectuoso.
Todd Gamblin

35
"Es relativamente fácil optimizar un programa correcto, pero es mucho más difícil corregir un programa optimizado".
gradbot

20
Inge: no estoy seguro de que estés en el camino correcto allí. Sí, C # se implementa en otro idioma, pero el compilador JIT está generando código de máquina, por lo que no es un lenguaje interpretado. Por lo tanto, no está limitado por su implementación en C ++. No estoy seguro de por qué crees que agregar algún administrador a algo inherentemente lo hace más rápido.
Martin Probst

202

C # puede no ser más rápido, pero te hace a TI / ME más rápido. Esa es la medida más importante para lo que hago. :)


68
Jaja, hay una buena cita de Larry Wall sobre el tema. Está hablando de Perl, pero se puede pensar en todas las discusiones relacionadas con los lenguajes y el rendimiento: "... los lenguajes informáticos anteriores, como Fortran y C, se diseñaron para hacer un uso eficiente del costoso hardware de la computadora. Por el contrario, Perl está diseñado para hacer un uso eficiente de los costosos programadores de computadoras "
Falaina

6060
1. "C # es mucho más rápido que C ++" 2. "No puede ser cierto" 1. "Seguro que puede" 2. "¿Por cuánto?" 1. "Por lo general, de 3 a 4 meses"
Dmitry S.

2
para C ++ que realmente depende de las bibliotecas que use, C # no suele ser más rápido, .NET lo es, cuando habla de productividad
Ion Todirel

Es la misma razón por la que podría usar Python en lugar de C para escribir código ... pero después de crear algunos cálculos pesados ​​puede sentir la diferencia en el rendimiento.
Ch3shire

Eso depende de lo que estás acostumbrado. Programo mucho más rápido en C ++ de lo que tendría en C #. El conocimiento de la biblioteca es una gran parte de eso, ya que no desea reinventar la rueda para tareas básicas. El principal problema de C / C ++ era la gestión de punteros, que se resuelve prácticamente con punteros inteligentes. Dicho esto, C ++ grave carece de una biblioteca extensa como las ofertas de .NET y Java y eso puede acelerar el desarrollo en gran medida. Esto no se resolverá pronto, ya que a los niños estándar les gusta dedicar su tiempo a mejoras de plantilla en lugar de extensiones de biblioteca.
gast128

87

Son cinco naranjas más rápido. O más bien: no puede haber una respuesta general (correcta). C ++ es un lenguaje compilado estáticamente (pero también hay una optimización guiada por perfil), C # se ejecuta con la ayuda de un compilador JIT. Hay tantas diferencias que preguntas como "cuánto más rápido" no se pueden responder, ni siquiera dando órdenes de magnitud.


177
¿Tiene alguna evidencia que respalde su escandaloso reclamo de cinco naranjas? Todos mis experimentos apuntan a 2 naranjas como máximo, con una mejora de 3 mangos al hacer la metaprogramación de plantillas.
Alex

42
En la levadura no está clamando sus entremeses de magnitud más rápido.
Chris

11
Según mi experiencia, son más de 5.2 naranjas. Pero esto depende de la fruta-o-metro que use.
Dio F

44
Actualización, StackOverflow se equivocó y maneja los comentarios ineficientes, por lo tanto, menos bananas (300 bananas peor de lo que debería ser): meta.stackexchange.com/questions/254534/…
KeksArmee

87

Comenzaré por estar en desacuerdo con parte de la respuesta aceptada (y bien votada) a esta pregunta al afirmar:

En realidad, hay muchas razones por las cuales el código JITted se ejecutará más lentamente que un programa C ++ (u otro lenguaje sin sobrecarga de tiempo de ejecución) correctamente optimizado, incluyendo:

  • los ciclos de cálculo gastados en el código JITting en tiempo de ejecución no están, por definición, disponibles para su uso en la ejecución del programa.

  • cualquier ruta activa en el JITter estará compitiendo con su código por instrucciones y caché de datos en la CPU. Sabemos que el caché domina cuando se trata de rendimiento y los lenguajes nativos como C ++ no tienen este tipo de contención, por definición.

  • El presupuesto de tiempo de un optimizador de tiempo de ejecución está necesariamente mucho más limitado que el de un optimizador de tiempo de compilación (como señaló otro comentarista)

En pocas palabras: En última instancia, será casi seguro que será capaz de crear una implementación más rápida en C ++ de lo que podía en C # .

Ahora, dicho esto, cuánto más rápido realmente no es cuantificable, ya que hay demasiadas variables: la tarea, el dominio del problema, el hardware, la calidad de las implementaciones y muchos otros factores. Deberá realizar pruebas en su escenario para determinar la diferencia en el rendimiento y luego decidir si vale la pena el esfuerzo y la complejidad adicionales.

Este es un tema muy largo y complejo, pero creo que vale la pena mencionar, en aras de la exhaustividad, que el optimizador de tiempo de ejecución de C # es excelente y es capaz de realizar ciertas optimizaciones dinámicas en tiempo de ejecución que simplemente no están disponibles para C ++ con su tiempo de compilación ( estático) optimizador. Incluso con esto, la ventaja sigue siendo típicamente profunda en la corte de la aplicación nativa, pero el optimizador dinámico es la razón del calificador " casi seguro" dado anteriormente.

-

En términos de rendimiento relativo, también me perturbaron las cifras y las discusiones que vi en algunas otras respuestas, así que pensé en intervenir y, al mismo tiempo, brindar algo de apoyo para las declaraciones que hice anteriormente.

Una gran parte del problema con esos puntos de referencia es que no puede escribir código C ++ como si estuviera escribiendo C # y esperar obtener resultados representativos (por ejemplo, realizar miles de asignaciones de memoria en C ++ le dará números terribles).

En cambio, escribí un código C ++ un poco más idiomático y lo comparé con el código C # que @Wiory proporcionó. Los dos cambios principales que hice al código C ++ fueron:

1) vector usado :: reserve ()

2) aplanó la matriz 2d a 1d para lograr una mejor ubicación de caché (bloque contiguo)

C # (.NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

Tiempo de ejecución (lanzamiento): Init: 124ms, Fill: 165ms

C ++ 14 (Clang v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

Tiempo de ejecución (Release): Init: 398µs (sí, eso es microsegundos), Fill: 152ms

Tiempo total de ejecución: C #: 289 ms, C ++ 152 ms (aproximadamente 90% más rápido)

Observaciones

  • Cambiar la implementación de C # a la misma implementación de matriz 1d produjo Init: 40ms, Fill: 171ms, Total: 211ms ( C ++ todavía era casi un 40% más rápido ).

  • Es mucho más difícil diseñar y escribir código "rápido" en C ++ que escribir código "regular" en cualquier idioma.

  • Es (quizás) asombrosamente fácil obtener un bajo rendimiento en C ++; vimos eso con el rendimiento de vectores sin reservas. Y hay muchas trampas como esta.

  • El rendimiento de C # es bastante sorprendente si se considera todo lo que sucede en tiempo de ejecución. Y ese rendimiento es relativamente fácil de acceder.

  • Más datos anecdóticos que comparan el rendimiento de C ++ y C #: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

La conclusión es que C ++ le brinda mucho más control sobre el rendimiento. ¿Quieres usar un puntero? ¿Una referencia? ¿Pila de memoria? ¿Montón? ¿Polimorfismo dinámico o eliminar la sobrecarga de tiempo de ejecución de una tabla virtual con polimorfismo estático (a través de plantillas / CRTP)? En C ++ que tiene que ... er, llegar a realizar todas estas opciones (y más) a sí mismo, a ser posible para que sus soluciones mejores direcciones el problema que está abordaje.

Pregúntese si realmente desea o necesita ese control, porque incluso para el ejemplo trivial anterior, puede ver que aunque hay una mejora significativa en el rendimiento, requiere una inversión más profunda para acceder.


16
@Quonux gracias por el comentario. Por supuesto, este no es un "programa real". El objetivo de los puntos de referencia fue refactorizar un punto de referencia C # ofrecido en otra parte de esta página como evidencia de que el código JITted es de alguna manera más rápido que el nativo, no lo es, y el punto de referencia era potencialmente engañoso para las personas nuevas.
U007D

99
@Quonux, ¿por qué tienes que escribir así? Es la gente como tú la que me disgusta de stackoverflow.
Markus Knappen Johansson

55
@MarkusKnappenJohansson Tuve un mal día;), también soy un humano, eliminé mi voto negativo, pero mi opinión aún se aplica. Oh, por favor, no me desagrada SO solo porque hay algunas personas "estúpidas" :). Que tengas uno bueno.
Quonux

99
PUNTO DE REFERENCIA COMPLETAMENTE ENGAÑOSO. En la versión C ++, simplemente está reservando parte de la memoria (y luego se maravilla de cómo esa operación tarda unos microsegundos en ejecutarse). En la versión C # estás creando 5000 ARRAYS (instanciando objetos en la memoria). C ++ es más rápido que C # ... pero la diferencia no está cerca del 40% ... en este momento está más dentro del rango de <10%. Lo que ilustra su ejemplo es que los programadores deben seguir el lenguaje de su elección (y desde su perfil es obvio que usted es un programador profesional de C ++). En C # puede hacer una matriz 2D int[,]... siguiendo con un ejemplo.
nikib3ro

3
Por lo que puedo decir, el código en su ejemplo de C ++ literalmente solo asigna la memoria con anticipación. La implementación adecuada de C # simplemente escribiría 'List <double> arrs = new List <double> (ROWS * COLS)' que asigna la memoria requerida para indexar una matriz de 2 dimensiones en formato de 1 dimensión (por ejemplo, lo que hizo en C ++). No hay absolutamente ninguna razón para asignar una matriz bidimensional y aplanarla manualmente: la gran cantidad de iteraciones en su prueba previa es la causa del rendimiento de mierda. Me imagino que la sobrecarga aún estaría más en C #, pero no en una cantidad considerable.
JDSweetBeat

62

En mi experiencia (y he trabajado mucho con ambos lenguajes), el principal problema con C # en comparación con C ++ es el alto consumo de memoria, y no he encontrado una buena manera de controlarlo. Fue el consumo de memoria lo que eventualmente ralentizaría el software .NET.

Otro factor es que el compilador JIT no puede permitirse demasiado tiempo para realizar optimizaciones avanzadas, ya que se ejecuta en tiempo de ejecución, y el usuario final lo notaría si lleva demasiado tiempo. Por otro lado, un compilador de C ++ tiene todo el tiempo que necesita para hacer optimizaciones en tiempo de compilación. Este factor es mucho menos significativo que el consumo de memoria, en mi humilde opinión.


66
En un proyecto en el trabajo tuvimos que extraer enormes cantidades de datos, incluida la retención de muchos GB en la memoria simultáneamente y realizar costosos cálculos en todo esto; esto requería un control preciso de todas las asignaciones, C ++ era prácticamente la única opción. +1 para C ++. Por otro lado, ese fue solo un proyecto, pasamos la mayor parte de nuestro tiempo escribiendo sistemas que interactuaban con simuladores lentos, y la depuración podría ser una pesadilla, por lo que desearía haber podido usar un lenguaje de optimización del tiempo del programador para todo ese otro cosas.
Bogatyr

77
@IngeHenriksen: Conozco bien el patrón Dispose, pero no ayuda en absoluto con la memoria administrada.
Nemanja Trifunovic

10
@IngeHenriksen eliminarlo solo garantiza que se haya llamado al método Dispose. La eliminación nunca libera la memoria recolectada de basura. El método Dispose solo está destinado a limpiar recursos no administrados, como identificadores de archivos, y no tiene nada que ver con la administración de memoria.
doug65536

1
@NemanjaTrifunovic: "El compilador JIT no puede permitirse demasiado tiempo para hacer optimizaciones avanzadas". ¿Puede citar algunas optimizaciones que los JIT no realizan porque tomarían demasiado tiempo?
Jon Harrop

55
@ user3800527: Incluso si agregar RAM siempre fue factible (y no lo es, imagine que Microsoft agrega RAM a cada usuario de MS Office) que no resolverá el problema. La memoria es jerárquica y un programa de C # tendrá muchos más errores de caché que uno de C ++.
Nemanja Trifunovic

35

Un escenario particular donde C ++ todavía tiene la ventaja (y lo hará, en los próximos años) ocurre cuando las decisiones polimórficas pueden predeterminarse en el momento de la compilación.

En general, la encapsulación y la toma de decisiones diferidas es algo bueno porque hace que el código sea más dinámico, más fácil de adaptar a los requisitos cambiantes y más fácil de usar como marco. Es por eso que la programación orientada a objetos en C # es muy productiva y puede generalizarse bajo el término "generalización". Desafortunadamente, este tipo particular de generalización tiene un costo en tiempo de ejecución.

Por lo general, este costo no es sustancial, pero hay aplicaciones en las que la sobrecarga de las llamadas a métodos virtuales y la creación de objetos pueden marcar la diferencia (especialmente porque los métodos virtuales impiden otras optimizaciones, como la inserción de llamadas a métodos). Aquí es donde C ++ tiene una gran ventaja porque puede usar plantillas para lograr un tipo diferente de generalización que no tiene impacto en el tiempo de ejecución pero no es necesariamente menos polimórfico que OOP. De hecho, todos los mecanismos que constituyen la OOP se pueden modelar utilizando solo técnicas de plantilla y resolución en tiempo de compilación.

En tales casos (y es cierto que a menudo están restringidos a dominios con problemas especiales), C ++ gana contra C # y lenguajes comparables.


66
En realidad, las máquinas virtuales Java (y probablemente .NET) hacen todo lo posible para evitar el despacho dinámico. Básicamente, si hay una manera de evitar los polimorfos, puede estar bastante seguro de que su VM lo hará.
Martin Probst

3
+1 Siempre tengo problemas para explicar esto a mis colegas de C # que conocen poco C ++ de una manera que les permita apreciar la importancia. Lo has explicado bastante bien.
Roman Starkov

99
@crtracy: está haciendo su apuesta sin aplicaciones informáticas de alto rendimiento. Considere el pronóstico del tiempo, la bioinformática y las simulaciones numéricas. El líder de rendimiento de C ++ en estas áreas no se reducirá, porque ningún otro código puede lograr un rendimiento comparable en el mismo nivel de alta abstracción.
Konrad Rudolph

55
@ Jon Manzanas y naranjas. Su reclamo específico fue "C # es un orden de magnitud más rápido que C ++ en el contexto de la metaprogramación", no "el uso de código precompilado es un orden de magnitud más rápido que el código interpretado". Mientras estamos en eso, su afirmación de que la generación de código de tiempo de ejecución es "más general" que la generación de código en tiempo de compilación también es claramente errónea: ambos tienen fortalezas y debilidades. La generación de código en tiempo de compilación utiliza el sistema de tipos para proporcionar seguridad de tipo estático; la generación de código de tiempo de ejecución no puede hacer eso ( puede proporcionar seguridad de tipo fuerte, pero no seguridad de tipo estático ).
Konrad Rudolph el

55
@ user3800527 Creo que te estás perdiendo el punto de esta respuesta. Por supuesto, puede solucionar este problema rompiendo la encapsulación y desplegando estructuras de bajo nivel; puede escribir ensamblados en (la mayoría) de cualquier idioma. Lo que hace que C ++ (casi) sea único, y especialmente adecuado para la programación de alto rendimiento, es que puede crear abstracciones de alto nivel que no tienen costo de tiempo de ejecución. Por lo tanto, no necesita escribir código similar a un ensamblado en C ++ para obtener un rendimiento superior: una escritura bien escrita sort(arr, generic_comparer)será tan eficiente como un bucle escrito a mano en C ++. Nunca estará en C #.
Konrad Rudolph

20

C ++ (o C para el caso) le brinda un control detallado sobre sus estructuras de datos. Si quieres jugar un poco, tienes esa opción. Las grandes aplicaciones Java o .NET administradas (OWB, Visual Studio 2005 ) que usan las estructuras de datos internas de las bibliotecas Java / .NET llevan el equipaje con ellas. He visto que las sesiones de diseño de OWB usan más de 400 MB de RAM y BIDS para el diseño de cubos o ETL llegando también a los cientos de MB.

En una carga de trabajo predecible (como la mayoría de los puntos de referencia que repiten un proceso muchas veces), un JIT puede obtener un código que esté optimizado lo suficientemente bien como para que no haya una diferencia práctica.

OMI en aplicaciones grandes, la diferencia no es tanto el JIT como las estructuras de datos que el código en sí está utilizando. Cuando una aplicación tiene mucha memoria, obtendrá un uso de caché menos eficiente. Los errores de caché en las CPU modernas son bastante caros. Donde C o C ++ realmente ganan es donde puede optimizar su uso de estructuras de datos para jugar bien con el caché de la CPU.


19

Para los gráficos, la clase de gráficos estándar de C # es mucho más lenta que GDI al que se accede a través de C / C ++. Sé que esto no tiene nada que ver con el lenguaje per se, más con la plataforma .NET total, pero Graphics es lo que se ofrece al desarrollador como reemplazo de GDI, y su rendimiento es tan malo que ni siquiera me atrevería a hacer gráficos. con eso.

Tenemos un punto de referencia simple que usamos para ver qué tan rápida es una biblioteca de gráficos, y eso es simplemente dibujar líneas aleatorias en una ventana. C ++ / GDI sigue siendo ágil con 10000 líneas, mientras que C # / Graphics tiene dificultades para hacer 1000 en tiempo real.


55
Me intrigó tu respuesta. ¿Ha probado el mismo punto de referencia con código inseguro y bits de bloqueo, y dibujando las líneas aleatorias usted mismo? Ahora eso sería algo interesante de ver.
Pedery

2
@Pedery no, no lo he hecho. simplemente usando GDI y .NET.Graphics de la manera más básica. ¿Qué quieres decir con "dibujar las líneas al azar tú mismo"?
QBziZ

1
Entonces, tal vez debería considerar probar esto para obtener métricas más realistas de cuán rápido puede ser C #. Aquí hay una buena descripción de la técnica: bobpowell.net/lockingbits.htm
Pedery

66
Eso no es lo que queremos hacer, poner píxeles separados en un búfer de cuadro nosotros mismos. Si tiene que implementar todo usted mismo, ¿cuál es el punto de tener una API / Plataforma para codificar? Para mí esto no es un argumento. Nunca necesitamos colocar píxeles separados en un framebuffer en GDI para dibujar líneas, y tampoco planeamos hacerlo en .NET. Desde mi punto de vista, utilizamos una métrica realista, y .NET resultó ser lento.
QBziZ

1
Bueno, tengo una ligera idea de qué es la detección de manchas, pero solo indicar un momento no prueba nada en absoluto. ¿Has escrito uno en C ++? En JavaScript? ¿Y los comparó con el de C #? Y además de eso, no creo que la detección de manchas esté usando muchas primitivas gráficas. Corrígeme si está equivocado, pero supongo que son algoritmos estadísticos que realizan operaciones en píxeles.
QBziZ

13

La recolección de basura es la razón principal por la que Java # NO PUEDE usarse para sistemas en tiempo real.

  1. ¿Cuándo ocurrirá el GC?

  2. ¿Cuánto tiempo tardará?

Esto no es determinista.


55
No soy un gran fanático de Java, pero no hay nada que diga que Java no puede usar un GC amigable en tiempo real.
Zan Lynx

55
Hay muchas implementaciones de GC en tiempo real si te interesa mirar. (GC es un área que está desbordando con trabajos de investigación)
Arafangion

FWIW, Richard Jones acaba de publicar una versión actualizada de su libro de recolección de basura que cubre, entre otras cosas, diseños de GC en tiempo real de última generación.
Jon Harrop

11
Este es un argumento sin sentido, Windows (y Linux) no son sistemas operativos en tiempo real. Su código C ++ podría intercambiarse por un número de ranuras de 18 ms en cualquier momento también.
Henk Holterman

2
@HenkHolterman Es cierto, pero siempre se puede escribir un cargador de arranque en conjunto, vincularlo a un arranque de kernel para su aplicación y ejecutar sus aplicaciones C ++ directamente contra el hardware (en RT por cierto). No puede hacer esto en C # y cualquier esfuerzo que haya visto solo imita el ensamblaje precompilado en C # y usa una tonelada de código C, lo que hace que no tenga sentido usar C #. Leer todo esto es un poco divertido, porque C # es realmente inútil sin el marco .NET.
zackery.fix

11

Hemos tenido que determinar si C # era comparable a C ++ en rendimiento y escribí algunos programas de prueba para eso (usando Visual Studio 2005 para ambos idiomas). Resultó que sin recolección de basura y solo considerando el lenguaje (no el marco) C # tiene básicamente el mismo rendimiento que C ++. La asignación de memoria es mucho más rápida en C # que en C ++ y C # tiene una ligera ventaja en el determinismo cuando los tamaños de datos aumentan más allá de los límites de la línea de caché. Sin embargo, todo esto finalmente tuvo que pagarse y hay un costo enorme en forma de resultados de rendimiento no deterministas para C # debido a la recolección de basura.


1
En C ++, tiene la opción de usar diferentes métodos de asignación, por lo que dependiendo de cómo se asignó la memoria (AOT?) En C #, podría hacerse de la misma manera (pero mucho más rápido) en C ++.
zackery.fix

55
@ zackery.fix .NET tiene una ventaja interesante en la asignación del montón, porque solo tiene que mover un puntero para asignar un nuevo objeto. Esto solo es factible debido al compactador de basura. Por supuesto, puedes hacer lo mismo en C ++, pero C ++ no hace eso. Es curioso cómo usas el mismo argumento para decir "C # podría pero no lo hace, por lo que es basura" y "C ++ no lo hace, pero podría, así que es increíble" :)
Luaan

9

Como de costumbre, depende de la aplicación. Hay casos en los que C # es probablemente mucho más lento, y otros casos en los que C ++ es 5 o 10 veces más rápido, especialmente en los casos en que las operaciones se pueden SIMD'd fácilmente.


El mejor caso para las máquinas virtuales será la compilación en tiempo de ejecución del código generado (por ejemplo, para que coincida con una expresión regular leída en tiempo de ejecución) porque los programas C ++ vanilla compilados estáticamente solo pueden usar la interpretación porque no tienen un compilador JIT incorporado.
Jon Harrop

Nota del futuro: .NET tiene soporte para SIMD y amigos desde aproximadamente 2014, aunque no se usa ampliamente.
Luaan

9

Sé que no es lo que estabas preguntando, pero C # a menudo es más rápido de escribir que C ++, lo cual es una gran ventaja en un entorno comercial.


2
Yo diría que es más rápido la mayor parte del tiempo :)
Trampa

8

C / C ++ puede funcionar mucho mejor en programas en los que hay matrices grandes o bucles / iteraciones pesadas sobre matrices (de cualquier tamaño). Esta es la razón por la que los gráficos son generalmente mucho más rápidos en C / C ++, porque las operaciones de matriz pesadas subyacen en casi todas las operaciones de gráficos. .NET es notoriamente lento en las operaciones de indexación de matrices debido a todas las comprobaciones de seguridad, y esto es especialmente cierto para las matrices multidimensionales (y, sí, las matrices rectangulares C # son incluso más lentas que las matrices irregulares C #).

Las bonificaciones de C / C ++ son más pronunciadas si se adhiere directamente a los punteros y evita Boost std::vectory otros contenedores de alto nivel, así como inlinetodas las funciones pequeñas posibles. Use matrices de la vieja escuela siempre que sea posible. Sí, necesitará más líneas de código para lograr lo mismo que hizo en Java o C # ya que evita los contenedores de alto nivel. Si necesita una matriz de tamaño dinámico, solo tendrá que recordar emparejarla new T[]con una delete[]instrucción correspondiente (o usarstd::unique_ptr): El precio de la velocidad adicional es que debe codificar con más cuidado. Pero a cambio, puede deshacerse de la sobrecarga de la memoria administrada / recolector de basura, que puede ser fácilmente el 20% o más del tiempo de ejecución de programas orientados a objetos en Java y .NET, así como aquellos administrados masivamente costos de indexación de matriz de memoria. Las aplicaciones de C ++ también pueden beneficiarse de algunos cambios ingeniosos del compilador en ciertos casos específicos.

Soy un programador experto en C, C ++, Java y C #. Recientemente tuve la rara ocasión de implementar exactamente el mismo programa algorítmico en los últimos 3 idiomas. El programa tenía muchas operaciones matemáticas y de matriz multidimensional. Lo optimicé mucho en los 3 idiomas. Los resultados fueron típicos de lo que normalmente veo en comparaciones menos rigurosas: Java fue aproximadamente 1.3 veces más rápido que C # (la mayoría de las JVM están más optimizadas que el CLR), y la versión de puntero sin formato de C ++ llegó aproximadamente 2.1 veces más rápido que C #. Tenga en cuenta que el programa C # solo usó código seguro; en mi opinión, también podría codificarlo en C ++ antes de usar la unsafepalabra clave.

Para que nadie piense que tengo algo en contra de C #, terminaré diciendo que C # es probablemente mi lenguaje favorito. Es el lenguaje de desarrollo más lógico, intuitivo y rápido que he encontrado hasta ahora. Hago todos mis prototipos en C #. El lenguaje C # tiene muchas ventajas pequeñas y sutiles sobre Java (sí, sé que Microsoft tuvo la oportunidad de corregir muchas de las deficiencias de Java entrando tarde al juego y posiblemente copiando Java). Brindis por la Calendarclase de Java a alguien? Si Microsoft alguna vez gasta un esfuerzo real para optimizar el CLR y el .NET JITter, C # podría hacerse cargo en serio. Estoy sinceramente sorprendido de que aún no lo hayan hecho: hicieron tantas cosas bien en el lenguaje C #, ¿por qué no seguir con optimizaciones de compilación impactantes? Quizás si todos suplicamos.


3
"solo tendrás que recordar emparejar tu new T[]con el correspondiente delete[]" - No, no lo haces. Hay std::unique_ptrque hacer eso por ti.
emlai

asumiendo que escribió algo en gráficos, ¿por qué escribir código seguro en C #? ¿Ha considerado usar un código inseguro y comparar de nuevo?
user3800527

7

> Por lo que he escuchado ...

Su dificultad parece ser decidir si lo que ha escuchado es creíble, y esa dificultad solo se repetirá cuando intente evaluar las respuestas en este sitio.

¿Cómo va a decidir si las cosas que la gente dice aquí son más o menos creíbles de lo que escuchó originalmente?

Una forma sería pedir evidencia .

Cuando alguien dice "hay algunas áreas en las que C # demuestra ser más rápido que C ++", pregúnteles por qué dicen eso , pídales que le muestren medidas, pídales que le muestren programas. A veces simplemente habrán cometido un error. A veces descubrirás que solo están expresando una opinión en lugar de compartir algo que pueden demostrar que es verdad.

A menudo, la información y la opinión se mezclarán en lo que la gente dice, y tendrá que intentar resolver cuál es cuál. Por ejemplo, de las respuestas en este foro:

  • "Tome los puntos de referencia en http://shootout.alioth.debian.org/ con mucho escepticismo, ya que estos prueban en gran medida el código aritmético, que probablemente no sea similar a su código".

    Pregúntese si realmente comprende lo que significa "estos códigos aritméticos en gran medida de prueba" , y luego pregúntese si el autor realmente le ha demostrado que su afirmación es cierta.

  • "Esa es una prueba bastante inútil, ya que realmente depende de qué tan bien se hayan optimizado los programas individuales; he logrado acelerar algunos de ellos de 4 a 6 veces o más, dejando en claro que la comparación entre programas no optimizados es bastante tonto."

    Pregúntese si el autor realmente le ha demostrado que ha logrado "acelerar algunos de ellos de 4 a 6 veces o más". ¡Es un reclamo fácil de hacer!


No podría estar más de acuerdo contigo y esa es la razón por la que pregunté en este foro ... Después de todo, las respuestas tienen que estar en algún lado, ¿no? :)
Trampa

1
Si. La respuesta es, depende.".
user49117

6

Para problemas 'vergonzosamente paralelos', cuando utilizo Intel TBB y OpenMP en C ++, he observado un aumento de rendimiento de aproximadamente 10 veces en comparación con problemas similares (matemáticos puros) realizados con C # y TPL. SIMD es un área donde C # no puede competir, pero también tuve la impresión de que TPL tiene una sobrecarga considerable.

Dicho esto, solo uso C ++ para tareas críticas de rendimiento en las que sé que podré realizar múltiples subprocesos y obtener resultados rápidamente. Para todo lo demás, C # (y ocasionalmente F #) está bien.


5

Es una pregunta extremadamente vaga sin respuestas definitivas reales.

Por ejemplo; Prefiero jugar juegos en 3D creados en C ++ que en C #, porque el rendimiento es mucho mejor. (Y sé XNA, etc., pero no se acerca de verdad).

Por otro lado, como se mencionó anteriormente; debe desarrollarse en un lenguaje que le permita hacer lo que quiera rápidamente y, si es necesario, optimizarlo.


44
¿Podría nombrar algunos ejemplos? Juegos escritos en C # que has encontrado lento
Karl

1
Incluso las aplicaciones de ejemplo que vinieron con la instalación se sintieron lentas.
David The Man

99
El recolector de basura es una gran responsabilidad al hacer juegos con C #, ya que puede patear en cualquier momento, causando pausas importantes. La gestión explícita de la memoria termina siendo más fácil para el desarrollo del juego.
postfuturista

3
La mayoría de los juegos modernos están limitados por GPU. Para tales juegos, no importa si la lógica (ejecutada en la CPU) es un 10% más lenta, todavía están limitados por la GPU, no por la CPU. El recolector de basura es un problema real, ya que provoca congelaciones cortas aleatorias si las asignaciones de memoria no se ajustan bien.
Michael Entin

2
@postfuturist: Eso no es cierto en PC; el recolector de basura hace un buen trabajo al entrar y salir, nunca he tenido ningún problema con él. Sin embargo, en XBox 360 y Zune / Windows-7-Phone, el recolector de basura no es tan inteligente como en una PC; Nunca he escrito para ninguno, pero las personas que me han dicho que el recolector de basura es un gran problema.
BlueRaja - Danny Pflughoeft 01 de

5

Los lenguajes .NET pueden ser tan rápidos como el código C ++, o incluso más rápido, pero el código C ++ tendrá un rendimiento más constante ya que el tiempo de ejecución .NET tiene que pausar para GC , incluso si es muy inteligente sobre sus pausas.

Entonces, si tiene algún código que debe ejecutarse constantemente de manera rápida y sin pausa, .NET introducirá latencia en algún momento , incluso si tiene mucho cuidado con el tiempo de ejecución GC.


66
-1: Esto es en realidad un mito. En primer lugar, la latencia de C ++ idiomático es realmente horrible y, a menudo, mucho peor que .NET porque RAII causa avalanchas de destructores cuando grandes estructuras de datos caen fuera del alcance, mientras que los GC modernos son incrementales y los .NET incluso son concurrentes. En segundo lugar, puede eliminar completamente las pausas de GC en .NET al no asignar.
Jon Harrop

2
Si haces esto, debes renunciar a usar el BCL ya que la mayoría de los métodos crean objetos transitorios.
Florian Doyon

55
Esto es bastante cierto, no fue hasta .net 4 que el GC se hizo incremental. Tenemos una gran aplicación C # que se detiene por segundos para GC. Para aplicaciones críticas de rendimiento, esto es un asesino.
Justin

55
Hay una razón por la cual los programas que tienden a impulsar el hardware tienden a usar C ++. Tiene un control más preciso cuando lo necesita. El rendimiento solo es clave cuando empuja el sistema; de lo contrario, use C # o Java para ahorrar tiempo.
VoronoiPotato

44
Si no puede administrar el comportamiento de la memoria caché, no puede superar el código optimizado de C ++. Una falta de caché de L1 a la memoria principal podría ralentizar su operación 100 veces.
DAG

4

En teoría, para una aplicación de tipo servidor de larga ejecución, un lenguaje compilado JIT puede ser mucho más rápido que una contraparte compilada de forma nativa. Dado que el lenguaje compilado JIT generalmente se compila primero en un lenguaje intermedio de nivel bastante bajo, de todos modos puede hacer muchas optimizaciones de alto nivel en el momento de la compilación. La gran ventaja es que el JIT puede continuar compilando secciones de código sobre la marcha a medida que obtiene más y más datos sobre cómo se usa la aplicación. Puede organizar las rutas de código más comunes para permitir que la predicción de bifurcación tenga éxito con la mayor frecuencia posible. Puede reorganizar bloques de código separados que a menudo se unen para mantenerlos a ambos en la memoria caché. Puede gastar más esfuerzo optimizando los bucles internos.

Dudo que esto sea hecho por .NET o cualquiera de los JRE, pero estaba siendo investigado cuando estaba en la universidad, por lo que no es irrazonable pensar que este tipo de cosas puedan llegar al mundo real en algún momento pronto .


4

Aplicaciones que requieren acceso intensivo a la memoria, por ejemplo. la manipulación de imágenes suele estar mejor escrita en un entorno no administrado (C ++) que administrada (C #). Los lazos internos optimizados con aritmética de puntero son mucho más fáciles de controlar en C ++. En C #, es posible que deba recurrir a un código inseguro para incluso acercarse al mismo rendimiento.


4

Lo probé vectoren C ++ y C # equivalente, Listy en matrices 2d simples.

Estoy usando las ediciones Express de Visual C # / C ++ 2010. Ambos proyectos son simples aplicaciones de consola, las he probado en versión estándar (sin configuraciones personalizadas) y modo de depuración. Las listas de C # se ejecutan más rápido en mi PC, la inicialización de la matriz también es más rápida en C #, las operaciones matemáticas son más lentas.

Estoy usando Intel Core2Duo P8600@2.4GHz, C # - .NET 4.0.

Sé que la implementación de vectores es diferente de la lista C #, pero solo quería probar las colecciones que usaría para almacenar mis objetos (y poder usar el descriptor de acceso).

Por supuesto, necesita borrar la memoria (digamos para cada uso de new), pero quería mantener el código simple.

Prueba de vectores C ++ :

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

Prueba de lista de C #:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++ - matriz:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C # - matriz:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

Hora: (lanzamiento / depuración)

C ++

  • 600/606 ms de inicio de matriz,
  • 200/270 ms relleno de matriz,
  • 1sec / 13sec vector init & fill.

(Sí, 13 segundos, siempre tengo problemas con las listas / vectores en modo de depuración).

C#:

  • 20/20 ms de inicio de matriz,
  • Relleno de matriz de 403/440 ms,
  • 710/742 ms lista de inicio y relleno.

1
Me encantaría ver el índice de acceso en std :: list. De todos modos, lleva 37 segundos con la lista, el modo de liberación. Lanzamiento sin depuración: lista 3s, vector 0,3 s. Probablemente un problema de desreferenciación o algo. Muestra: nopaste.pl/12fb
Wiory

2
Para mediciones más precisas, no debería usar System.DateTime.Now, sino la clase Cronómetro .
Sam

44
Parte de la razón por la que obtiene tiempos de llenado tan lentos para el vector en C ++ es que está utilizando push_back. Esto ha demostrado en numerosas publicaciones que es más lento que usar el método at o el operador []. Para usar cualquiera de esos métodos, debe usar el método de cambio de tamaño o de reserva. Además, la razón por la que su inicialización está tardando tanto en el caso del vector c ++ es que está obligando a un operador de copia o asignación (no estoy seguro de cuál en este caso) para inicializar su vector c ++. Para la matriz en c ++ hay un algoritmo que usa 2 llamadas nuevas en lugar de 5001 y también es más rápido en iteración.
Zachary Kraus

55
Creo que no hiciste c ++ de manera adecuada. Solo un vistazo y encontré tantos problemas. Por ejemplo, vector <vector <double>> myList = vector <vector <double>> ()
DAG

2
Guau. No estoy seguro de qué conclusiones se pueden sacar de la comparación de listas frente a matrices redimensionables, pero si va a usar vectores como este, querrá aprender sobre reserve (), amigo mío, reserve ().
U007D

3

Bueno, eso depende. Si el código de bytes se traduce en código de máquina (y no solo JIT) (quiero decir, si ejecuta el programa) y si su programa usa muchas asignaciones / desasignaciones, podría ser más rápido porque el algoritmo GC solo necesita una pasada (en teoría) a través de toda la memoria una vez, pero las llamadas normales de malloc / realloc / free C / C ++ provocan una sobrecarga en cada llamada (sobrecarga de llamada, sobrecarga de estructura de datos, errores de caché;)).

Por lo tanto, es teóricamente posible (también para otros lenguajes GC).

Realmente no veo la desventaja extrema de no poder usar la metaprogramación con C # para la mayoría de las aplicaciones, porque la mayoría de los programadores no la usan de todos modos.

Otra gran ventaja es que el SQL, como la "extensión" LINQ , brinda oportunidades para que el compilador optimice las llamadas a las bases de datos (en otras palabras, el compilador podría compilar todo el LINQ en un binario "blob" donde las funciones llamadas están en línea o para su uso optimizado, pero estoy especulando aquí).


1
Cualquier desarrollador de C ++ adecuado no se encontrará con los problemas que usted describe. Solo los malos programadores de C que decidieron aplicar clases en sus programas y llamarlo C ++ tienen esos problemas.
Más claro el

1
por el amor de los dioses, esto tiene 8 años, OMFGz
Quonux

siéntase libre de dar una respuesta mejor y más actualizada
Quonux

2

Supongo que hay aplicaciones escritas en C # que se ejecutan rápidamente, así como también hay más aplicaciones escritas en C ++ que se ejecutan rápidamente (bueno, C ++ es más antiguo ... y también toman UNIX ...)
. La pregunta es: ¿qué es esa cosa, usuarios? y los desarrolladores se quejan de ...
Bueno, en mi humilde opinión, en el caso de C # tenemos una interfaz de usuario muy cómoda, una jerarquía de bibliotecas muy agradable y un sistema de interfaz completo de CLI. En el caso de C ++, tenemos plantillas, ATL, COM, MFC y todo el código de código escrito y en ejecución como OpenGL, DirectX, etc. en un segundo: ¡bang !, está atascado).
Escribir código en C # muy simple y rápido (sin olvidar que también aumenta la posibilidad de errores. En el caso de C ++, los desarrolladores se quejan de pérdidas de memoria, - significa aplastamientos, llamadas entre archivos DLL, así como de "infierno de DLL" - problema con soporte y bibliotecas de reemplazo por las más nuevas ...
Creo que cuanta más habilidad tenga en el lenguaje de programación, más calidad (y velocidad) caracterizará su software.


2

Lo diría de esta manera: los programadores que escriben código más rápido, son los que están más informados sobre lo que hace que las máquinas actuales funcionen rápido, y por cierto, también son los que usan una herramienta adecuada que permite un nivel bajo y determinista preciso Técnicas de optimización. Por estas razones, estas personas son las que usan C / C ++ en lugar de C #. Yo iría tan lejos como afirmar esto como un hecho.


Notch codificó Minecraft para que sea bastante rápido considerando la cantidad de datos que está manipulando. Además, lo codificó principalmente solo en un período de tiempo relativamente corto, algo que habría sido prácticamente imposible en C ++. Sin embargo, estoy de acuerdo con las técnicas de optimización: si tiene el tiempo de desarrollo adicional de 10x para gastar y su código se ejecuta dos veces más rápido, probablemente valga la pena.
Bill K

2

Si no me equivoco, las plantillas de C # se determinan en tiempo de ejecución. Esto debe ser más lento que las plantillas de tiempo de compilación de C ++.

Y cuando toma todas las otras optimizaciones en tiempo de compilación mencionadas por muchos otros, así como la falta de seguridad que, de hecho, significa más velocidad ...

Yo diría que C ++ es la opción obvia en términos de velocidad bruta y consumo mínimo de memoria. Pero esto también se traduce en más tiempo desarrollando el código y asegurando que no está perdiendo memoria o causando excepciones de puntero nulo.

Veredicto:

  • C #: desarrollo más rápido, ejecución más lenta

  • C ++: desarrollo lento, ejecución más rápida.


1

Realmente depende de lo que intente lograr en su código. He oído que es solo una leyenda urbana que hay alguna diferencia de rendimiento entre VB.NET, C # y C ++ administrado. Sin embargo, he encontrado, al menos en las comparaciones de cadenas, que C ++ superó los pantalones de C #, que a su vez supera los pantalones de VB.NET.

De ninguna manera he hecho ninguna comparación exhaustiva en la complejidad algorítmica entre los idiomas. También estoy usando la configuración predeterminada en cada uno de los idiomas. En VB.NET estoy usando configuraciones para requerir la declaración de variables, etc. Aquí está el código que estoy usando para C ++ administrado: (Como puede ver, este código es bastante simple). Estoy ejecutando lo mismo en los otros idiomas en Visual Studio 2013 con .NET 4.6.2.

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}

1

Existen algunas diferencias importantes entre C # y C ++ en el aspecto del rendimiento:

  • C # está basado en GC / montón. La asignación y el GC en sí son generales como la no localidad del acceso a la memoria
  • Los optimizadores de C ++ se han vuelto muy buenos a lo largo de los años. Los compiladores JIT no pueden alcanzar el mismo nivel ya que solo tienen un tiempo de compilación limitado y no ven el alcance global

Además de eso, la competencia del programador también juega un papel. He visto un código C ++ incorrecto donde las clases se pasan por valor como argumento en todo el lugar. En realidad, puede empeorar el rendimiento en C ++ si no sabe lo que está haciendo.


0

> Después de todo, las respuestas tienen que estar en algún lado, ¿no? :)

Umm no.

Como se observó en varias respuestas, la pregunta está subespecificada en formas que invitan preguntas en respuesta, no respuestas. Para tomar solo un camino:

¿Y luego qué programas? Cual maquina Que sistema operativo ¿Qué conjunto de datos?


Estoy completamente de acuerdo. Me pregunto por qué las personas esperan una respuesta precisa (63.5%), cuando hacen una pregunta general. No creo que haya una respuesta general a este tipo de preguntas.
llámame Steve el

@callmesteve: Sé lo que quieres decir, pero tu última oración debería sonar como clavos sobre una pizarra para cualquier programador.
Wouter van Nifterick el

1
Esto no parece responder a la pregunta, y se lee más como un comentario o despotricar.
Tas

-13

Inspirado por esto, hice una prueba rápida con el 60 por ciento de la instrucción común necesaria en la mayoría de los programas.

Aquí está el código C #:

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

La matriz de cadenas y la lista de matrices se usan a propósito para incluir esas instrucciones.

Aquí está el código c ++:

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

El tamaño del archivo de entrada que utilicé fue de 40 KB.

Y aquí está el resultado:

  • El código C ++ se ejecutó en 9 segundos.
  • Código C #: ¡4 segundos!

Oh, pero esto estaba en Linux ... Con C # ejecutándose Mono ... Y C ++ con g ++.

OK, esto es lo que obtuve en Windows - Visual Studio 2003 :

  • El código C # se ejecutó en 9 segundos.
  • Código C ++: ¡horrible 370 segundos!

77
Está utilizando diferentes estructuras de datos y código de biblioteca allí, aunque "370 segundos" indica algo horrible: por casualidad, no lo está ejecutando en el depurador, ¿verdad? Sospecho que el rendimiento de la biblioteca CSV que está utilizando es más interesante que el rendimiento del lenguaje que está utilizando. Yo cuestionaría el uso de un vector en ese contexto, y qué optimizaciones usaste. Además, es ampliamente conocido que iostreams (en particular, "myfile << * j <<", ";") es mucho más lento que otros métodos de escritura en el archivo, al menos para algunas implementaciones comunes.
Arafangion

66
Finalmente, estás haciendo más trabajo en la versión C ++. (¿Por qué está limpiando csvColumn, csvElement y csvLines?)
Arafangion

2
Cada iteración del ciclo while va a destruir y reconstruir un std :: istream y un std :: vector y un std :: string. El cuerpo while queda fuera de alcance en cada iteración, todas esas variables dentro del alcance while se van a destruir y construir en cada iteración.
doug65536

1
desde el aspecto de leer su código de C ++ que está tratando de copiar de un archivo a otro. En lugar de utilizar las complejas interacciones entre secuencias de archivos, cadenas, vectores y secuencias de cadenas, podría haber copiado la secuencia del archivo de entrada en la secuencia del archivo de salida. Esto habría ahorrado mucho tiempo y memoria.
Zachary Kraus

2
para hacer pruebas de velocidad, pruebe cosas en memoria no llegue al disco IO, a menos que realice sus pruebas en los últimos SSD y esté dedicado a su aplicación de rendimiento. Como las computadoras escriben constantemente en el disco, incluso si no toca el teclado.
user3800527
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.