2009-02-08 5 views
6

Me he estado preguntando durante bastante tiempo sobre cómo gestionar la memoria en mi próximo proyecto. Que está escribiendo una DSL en C/C++.¿La basura recolectada C será más rápida que C++?

Se puede hacer de cualquiera de las tres maneras.

  1. Referencia contada C o C++.
  2. Recogida de basura C.
  3. En C++, copiar clase y estructuras de pila a pila y gestionar las cadenas por separado con algún tipo de GC.

La comunidad probablemente ya tenga mucha experiencia en cada uno de estos métodos. ¿Cuál será más rápido? ¿Cuáles son los pros y los contras de cada uno?

Una pregunta secundaria relacionada. ¿Malloc/free será más lento que asignar un gran bloque al principio del programa y ejecutar mi propio administrador de memoria sobre él? .NET parece hacerlo. Pero estoy confundido por qué no podemos contar con OS para hacer este trabajo mejor y más rápido de lo que podemos hacer nosotros mismos.

Respuesta

8

¡Todo depende! Esa es una pregunta bastante abierta. ¡Necesita un ensayo para responderlo!

Hey .. Aquí hay uno que alguien preparado anteriormente:

http://lambda-the-ultimate.org/node/2552

http://www.hpl.hp.com/personal/Hans_Boehm/gc/issues.html

Depende de lo grande sus objetos son, cuántos de ellos hay, la rapidez con que están siendo asignados y descartado, cuánto tiempo desea invertir optimizando y ajustando para hacer optimizaciones. Si conoce los límites de la cantidad de memoria que necesita, para obtener un rendimiento rápido, creo que no puede superar la tarea de obtener toda la memoria que necesita del sistema operativo por adelantado, y luego administrarla usted mismo.

La razón por la que la memoria de asignación lenta del sistema operativo es que se trata de muchos procesos y memoria en el disco y en RAM, por lo que para obtener memoria debe decidir si hay suficiente. Posiblemente, podría tener que paginar otro proceso de memoria desde el ram al disco para que pueda darle suficiente. Están pasando muchas cosas. Por lo tanto, administrarlo usted mismo (o con un montón recopilado por GC) puede ser mucho más rápido que ir al sistema operativo para cada solicitud. Además, el sistema operativo generalmente se ocupa de trozos de memoria más grandes, por lo que puede redondear el tamaño de las solicitudes que realiza, lo que significa que podría perder memoria.

¿Tiene un requisito realmente difícil para ir súper rápido? Muchas aplicaciones DSL no necesitan un rendimiento sin procesar.Sugiero ir con lo que sea más simple de codificar. Podría pasar toda su vida escribiendo sistemas de administración de memoria y preocupándose por cuál es el mejor.

+0

¿Estás diciendo que todo esto dependerá de qué * idioma *, C o C++, uno usa? Dado que en cualquiera de estos lenguajes, uno tiene que implementar GC uno mismo, creo que no hay variación por idioma, solo por variación de algoritmo. –

+0

No estoy del todo seguro de lo que estás preguntando. Pero, los mismos algoritmos de administración de memoria se pueden aplicar a ambos idiomas. Sin embargo, en C++ haría algo como anular el operador nuevo y eliminar para implementarlo. En C no estoy seguro; posiblemente nombre sus propias funciones y asegúrese de usarlas para todas las asignaciones. –

4

uh ... Depende de cómo usted escriba el sistema de recolección de basura para su DSL. Ni C ni C++ vienen con una instalación de recolección de basura incorporada, pero cualquiera podría usarse para escribir un recolector de basura muy eficiente o muy ineficiente. Escribir una cosa así, por cierto, es una tarea no trivial.

Las DSL a menudo se escriben en lenguajes de nivel superior como Ruby o Python específicamente porque el escritor del idioma puede aprovechar la recolección de basura y otras instalaciones del idioma. C y C++ son excelentes para escribir lenguajes completos de resistencia industrial, pero sin duda necesita saber lo que está haciendo para usarlos: el conocimiento de yacc y lex es especialmente útil aquí, pero una buena comprensión de dynamic memory management también es importante, como usted dice. También puede consultar keykit, una DSL de música de código abierto escrita en C, si todavía le gusta la idea de una DSL en C/C++.

1

Una pregunta secundaria relacionada. ¿Malloc/free será más lento que asignar un gran plato al principio del programa y ejecutar mi propio administrador de memoria sobre él? .NET parece hacerlo. Pero estoy confundido por qué no podemos contar con OS para hacer este trabajo mejor y más rápido de lo que podemos hacer nosotros mismos.

El problema de dejar que el SO maneje la asignación de memoria es que introduce un comportamiento indeterminado. El programador no tiene forma de saber cuánto tiempo tardará el sistema operativo en devolver un nuevo fragmento de memoria: una asignación puede ser bastante costosa si la memoria tiene que ser asignada al disco.

Preallocación por lo tanto podría sea una buena idea, especialmente cuando se utiliza un recolector de basura copiado. Aumentará el consumo de memoria, pero la asignación será rápida porque en la mayoría de los casos solo será un incremento de puntero.

+0

El sistema operativo (o en realidad, las bibliotecas, como malloc asigna grandes porciones y luego las distribuye pieza por pieza a su programa) es un asignador de propósito general. Si puede restringir su asignador de alguna manera, puede hacerlo más rápido. –

+0

La lectura/escritura de la memoria que ya ha sido asignada también puede ser bastante costosa si ha sido asignada al disco. :) – bk1e

3

Con la mayoría de las implementaciones de recolección de basura, la asignación puede ver una mejora de velocidad, pero luego tiene el costo adicional de la fase de recopilación que se puede desencadenar en cualquier momento de la ejecución del programa, lo que ocasiona un retraso repentino (aparentemente aleatorio).

En cuanto a su segunda pregunta, depende de sus algoritmos de gestión de memoria. Estarías seguro siguiendo la implementación malloc predeterminada de tu biblioteca, pero hay alternativas que ofrecen un mejor rendimiento.

4

¿Por qué la basura recolectada C sería más rápida que C++? Los únicos recolectores de basura disponibles para C son cosas bastante ineficientes, más diseñados para tapar las pérdidas de memoria que para mejorar realmente la calidad de su código.

En cualquier caso, C++ tiene el potencial de alcanzar un mejor rendimiento con menos código (tenga en cuenta que es solo un potencial. También es muy posible escribir código C++ mucho más lento que el equivalente C).

Teniendo en cuenta el estado actual de ambos idiomas, los GC no mejorarán en la actualidad el rendimiento de su código. Los GC se pueden hacer muy eficientes en los lenguajes diseñados para ello. C/C++ no están entre esos. ;)

Aparte de eso, es imposible decirlo. Los idiomas no tienen velocidad. No tiene sentido preguntar qué idioma es más rápido. Depende de 1) el código específico, 2) del compilador que lo compila, y 3) del sistema en el que se ejecuta (tanto el hardware como el sistema operativo).

malloc es una operación bastante lenta, mucho más lenta que los equivalentes de .NET, así que sí, si está realizando una gran cantidad de pequeñas asignaciones, puede ser mejor asignar una gran cantidad de memoria una vez, y luego usar trozos de ese.

La razón es que el sistema operativo tiene que encontrar una porción libre de memoria, básicamente al seguir una lista vinculada de todas las áreas de memoria libres. En .NET, una llamada nueva() básicamente no es más que mover el puntero del montón tantos bytes como lo requiera la asignación.

0

Ni C ni C++ te darán basura gratis. Lo que le darán es bibliotecas de asignación de memoria (que proporcionan malloc/free, etc.). Hay muchos recursos en línea para algoritmos para escribir bibliotecas de recolección de basura. Un buen comienzo es link text

0

La mayoría de los idiomas que no son de GC asignará y desasignará la memoria según sea necesario y ya no será necesaria.Los lenguajes GC generalmente asignan trozos grandes de memoria de antemano y solo liberan la memoria cuando está inactiva y no en el medio de una tarea intensiva, así que voy a sí si el GC se activa en el momento correcto.

El lenguaje de programación D es un lenguaje recogido de basura y ABI compatible con C y parcialmente ABI compatible con C++. This Page muestra algunos puntos de referencia entre el rendimiento de cadena en C++ y D.

1

Como la gente ha señalado: GC es más rápido de asignar (porque acaba de aparecer el siguiente bloque en su lista), pero más lento en general (porque tiene que compactar el montón regularmente, para que los allocs sean rápidos).

así - ir para la solución de compromiso (que en realidad es muy muy bueno):

Usted crea sus propios montones, uno para cada tamaño de objeto que generalmente asignar (o 4 bytes, de 8 bytes, 16- byte, 32 bytes, etc.) entonces, cuando quiere una nueva pieza de memoria, toma el último 'bloque' en el montón apropiado. Debido a que se asigna previamente desde estos montones, todo lo que necesita hacer cuando se asigna es tomar el siguiente bloque libre. Esto funciona mejor que el asignador estándar porque está desperdiciando memoria: si desea asignar 12 bytes, abandonará un bloque completo de 16 bytes del montón de 16 bytes. Mantiene un mapa de bits de bloques v libres utilizados para que pueda asignarlos rápidamente sin desperdiciar mucha memoria ni necesidad de compactar.

Además, debido a que está ejecutando varios montones, los sistemas altamente paralelos funcionan mucho mejor ya que no es necesario bloquearlos con tanta frecuencia (es decir, tiene varios bloqueos para cada pila, por lo que no obtiene casi tanta)

Pruébelo: lo usamos para reemplazar el montón estándar en una aplicación muy intensa, el rendimiento aumentó bastante.

BTW. La razón por la que los asignadores estándar son lentos es que intentan no desperdiciar memoria, por lo que si asigna 5 bytes, 7 bytes y 32 bytes del montón estándar, mantendrá esos 'límites'. La próxima vez que necesite asignar, se desplazará a través de aquellos que buscan suficiente espacio para darle lo que usted solicitó. Eso funcionó bien para los sistemas de memoria baja, pero solo tienes que mirar cuánta memoria usan la mayoría de las aplicaciones hoy para ver que los sistemas GC vayan por el otro lado, y traten de hacer asignaciones lo más rápido posible sin preocuparte por la cantidad de memoria vano.

1

El problema tiene muchas variables, pero si su aplicación está escrita con la recolección de basura en mente, y si que explotan las características especiales de la Boehm collector, como las diferentes llamadas de asignación de bloques que no lo hacen contiene punteros, luego como regla general su aplicación - tendrá interfaces más simples - Se ejecutará un poco más rápido - requerirá de 1.2x a 2x el espacio que una aplicación similar que utilice administración de memoria explícita.

Para la documentación y las pruebas que respaldan estas afirmaciones, puede ver la información en el sitio web de Boehm, y también los diversos documentos de Ben Zorn sobre el costo medido de la recolección de basura conservadora.

Lo más importante es que ahorrará un montón de esfuerzo y no tendrá que preocuparse por una clase importante de errores de gestión de memoria.

El problema de C vs C++ es ortogonal, pero GC definitivamente será más rápido que el recuento de referencias, especialmente cuando no hay compatibilidad del compilador para el recuento de referencias.

0

Sugiero que si ha escrito un programa donde la asignación de memoria y la desasignación (explícita o GC) es el cuello de botella, entonces debe volver a pensar su arquitectura, diseño e implementación.

0

Si no desea administrar explícitamente la memoria, no use C/C++. Hay muchos idiomas con recuento de referencias o recolectores de basura compatibles con el compilador que probablemente funcionen mucho mejor para usted.

C/C++ están diseñados en un entorno en el que el programador gestiona su propia memoria. Intentar actualizar GC o ref contar con ellos puede ayudar a algunos, pero encontrará que debe comprometer el rendimiento del GC (porque no tiene ninguna alusión del compilador en cuanto a dónde podrían estar los punteros), o ' Encontraré formas nuevas y fascinantes de arruinar los recuentos de referencia, el GC o lo que sea.

Sé que suena como una buena idea, pero en realidad, debería elegir un lenguaje más adecuado para la tarea.

Cuestiones relacionadas