2008-11-21 23 views
18

¿Cuánto cuesta usar punteros inteligentes, en particular boost :: shared_ptr, más en comparación con los punteros en términos de tiempo y memoria? ¿El uso de punteros descubiertos es mejor para las partes de alto desempeño de los sistemas embebidos/integrados? ¿Recomendaría usar punteros simples o punteros inteligentes para componentes de rendimiento intensivo?C++ rendimiento de puntero inteligente

Respuesta

21

Desreferenciar punteros inteligentes suele ser trivial, sin duda para impulso en modo de lanzamiento. Todos los controles de impulso están en tiempo de compilación. (Los punteros inteligentes podrían, en teoría, hacer cosas inteligentes en los hilos). Esto aún deja muchas otras operaciones. Nicola mencionó construcción, copia y destrucción. Este no es el conjunto completo, sin embargo. Otras operaciones importantes son el intercambio, la asignación y el restablecimiento a NULL. Básicamente, cualquier operación que requiera inteligencia.

Tenga en cuenta que algunas de estas operaciones están excluidas por algunos punteros inteligentes. P.ej. boost::scoped_ptr ni siquiera se puede copiar, y mucho menos asignar. Como esto deja menos operaciones, la implementación se puede optimizar para estos pocos métodos.

De hecho, con la próxima TR1, es bastante probable que los compiladores obtengan mejores resultados con los punteros inteligentes que con los punteros sin formato. P.ej. es posible que un compilador pueda probar que un puntero inteligente que no se puede copiar no tiene alias en algunas situaciones, simplemente porque no se puede copiar. Piénselo: el aliasing ocurre cuando se crean dos punteros apuntando al mismo objeto. Si no se puede copiar el primer puntero, ¿cómo un segundo puntero apunta hacia el mismo objeto? (Hay formas de evitarlo también: el operador * tiene que devolver un valor l)

+0

Desafortunadamente, su idea de punteros inteligentes optimizados no funcionará, al menos en C++. Es posible que haya almacenado el puntero en otro lugar antes de colocarlo en el puntero inteligente. Además, es fácil (pero no aconsejable) sacar el puntero C sin procesar de un puntero inteligente, al hacer & * smart_ptr; –

+0

estoy de acuerdo con chris jefferson. nadie le impide almacenarlo en otro lugar antes de ponerlo en el puntero inteligente –

+0

He escrito una pequeña respuesta sobre alias aquí: http://stackoverflow.com/questions/270408/is-it-better-in-c-to- pass-by-value-or-pass-by-constant-reference # 271344 –

7

Boost proporciona diferentes punteros inteligentes. En general, tanto la ocupación de la memoria, que varía de acuerdo con el tipo de puntero inteligente, y el rendimiento no deberían ser un problema. Para una comparación de rendimiento, puede consultar este http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/smarttests.htm.

Como puede ver, solo se tienen en cuenta la construcción, la copia y la destrucción para comparar el rendimiento, lo que significa que quitarle un puntero inteligente tiene el mismo costo que un puntero sin formato.

el siguiente fragmento demuestra que no hay pérdida de rendimiento mediante el uso de un shared_ptr<> en lugar de un puntero en bruto:

#include <iostream> 
#include <tr1/memory> 

int main() 
{ 
#ifdef USE_SHARED_PTR 
    std::tr1::shared_ptr<volatile int> i(new int(1)); 
#else 
    volatile int * i = new int(1); 
#endif 

    long long int h = 0; 

    for(long long int j=0;j < 10000000000LL; j++) 
    { 
     h += *i; 
    } 

    std::cout << h << std::endl; 
    return 0; 
} 
2

Los punteros inteligentes de referencia (el tipo más común) solo cuestan más cuando los copia, los crea y los elimina. Este costo adicional puede ser sustancial si está copiando mucho, porque la mayoría de ellos son seguros para subprocesos.

Si solo desea un puntero de "autodeleción", existe el auto_ptr muy difamado, o el nuevo y brillante (pero no mucho soporte aún) unique_ptr de C++ 0x.

2

La última vez que probé, con VC6, el compilador no pudo optimizar el código con un puntero inteligente tan bien como con un puntero sin formato. Las cosas podrían haber cambiado desde entonces.

+2

La última vez que probé una versión anterior de boost (1.34 creo) con VC6, el compilador optimizó el incremento atómico del refcount para un weak_ptr. Eso hizo que las cosas funcionasen considerablemente más rápido, aunque causó bastantes cuelgues en las librerías enhebradas. – Michel

+0

VC6 Me doy cuenta que todavía se usa mucho en proyectos grandes que no pueden cambiar fácilmente, pero seamos justos aquí, no fue un compilador maduro hasta VC2003, la segunda versión dentro del ciclo de vida del producto VS.NET. – ApplePieIsGood

6

La única manera de lidiar con los problemas de rendimiento es perfilar su código. La mayor parte de los problemas de rendimiento se imagina de todos modos; solo el perfil le indicará dónde se encuentran sus cuellos de botella.

Si resulta que el uso de punteros inteligentes produce un cuello de botella donde los punteros crudos no lo hacen, ¡utilice punteros crudos! Hasta entonces, no me preocuparía demasiado por eso; la mayoría de las operaciones en punteros inteligentes son razonablemente rápidas. Probablemente compares cadenas demasiado a menudo (o algo así) para que importen.

2

Hay una casa intermedia a menudo pasada por alto entre un std::vector<T*> administrado "manualmente" (es decir, punteros sin formato) y un std::vector<boost::shared_ptr<T> >, en la forma de las clases boost::ptr_container.

Estos combinan el rendimiento de un contenedor de puntero sin procesar con la conveniencia de un contenedor de punteros inteligentes (es decir, proporcionan la funcionalidad que a las personas les gustaría contenedores STL de std::auto_ptr para proporcionar, if that worked).

Cuestiones relacionadas