(Esta no es una programación de juegos per se, pero estoy seguro de que si preguntara esto en SO, me dirían que no optimice prematuramente, a pesar de que la historia nos dice que cada juego grande termina preocupándose por estas cosas).
¿Existe algún documento en alguna parte que resuma las diferencias en el rendimiento, y particularmente el uso de memoria, entre diferentes implementaciones de bibliotecas estándar de C ++? Los detalles de algunas implementaciones están protegidos por NDA, pero una comparación entre incluso STLport vs. libstdc ++ vs. libc ++ vs. MSVC / Dinkumware (vs. ¿EASTL?) Parece ser inmensamente útil.
En particular, estoy buscando respuestas a preguntas como:
- ¿Cuánta sobrecarga de memoria se asocia con los contenedores estándar?
- ¿Qué contenedores, si los hay, hacen asignaciones dinámicas simplemente por ser declarados?
- ¿Std :: string hace copia en escritura? ¿Optimización de cadena corta? Cuerdas?
- ¿Std :: deque utiliza un buffer de anillo o es basura?
deque
siempre se implementaba en el STL con un vector.Respuestas:
En caso de que no encuentre dicho cuadro de comparación, la alternativa es inyectar un asignador propio a las clases STL en cuestión y agregar un poco de registro.
La implementación que probé (VC 8.0) no usa asignación de memoria simplemente declarando una cadena / vector / deque, pero para ello enumera y asigna. La cadena tiene una optimización de cadena corta, ya que agregar 3 caracteres no activó una asignación. La salida se agrega debajo del código.
Hasta ahora VC8 y STLPort 5.2 probados, aquí está la comparación (incluida en la prueba: cadena, vector, deque, lista, mapa)
Cadena de salida VC8 / vector / deque / list / map:
STLPort 5.2. salida compilada con VC8
Resultados EASTL , no hay deque disponible
fuente
std::string
no hace copia en escritura. CoW solía ser una optimización, pero tan pronto como varios hilos ingresan a la imagen, está más allá de una pesimismo: puede ralentizar el código por factores masivos. Es tan malo que el estándar C ++ 0x lo prohíbe activamente como estrategia de implementación. No solo eso, sino que la permisividad destd::string
distribuir iteradores mutables y referencias de caracteres significa que "escribir"std::string
implica casi todas las operaciones.La optimización de cadenas cortas es de aproximadamente 6 caracteres, creo, o algo así en esa región. Las cuerdas no están permitidas,
std::string
deben almacenar memoria contigua para lac_str()
función. Técnicamente, podría mantener una cuerda contigua y una cuerda en la misma clase, pero nadie lo hizo. Además, por lo que sé de las cuerdas, hacerlas seguras para manipularlas sería increíblemente lento, tal vez tan malo o peor que CoW.Ningún contenedor realiza la asignación de memoria al declararse en STL modernos. Los contenedores basados en nodos como list y map solían hacerlo, pero ahora tienen una optimización final integrada y no la necesitan. Es común realizar una optimización llamada "swaptimization" donde intercambia con un contenedor vacío. Considerar:
Por supuesto, en C ++ 0x esto es redundante, pero en C ++ 03, cuando esto se usaba comúnmente, si MahVariable asigna memoria en la declaración, entonces reduce la efectividad. Sé con
vector
certeza que esto se usó para reasignaciones más rápidas de contenedores como en el MSVC9 STL que eliminó la necesidad de copiar los elementos.deque
utiliza algo que se conoce como una lista vinculada desenrollada. Básicamente es una lista de matrices, generalmente de tamaño fijo en el nodo. Como tal, para la mayoría de los usos, conserva los beneficios de ambas estructuras de datos: acceso contiguo y eliminación de O (1) amortizada, y puede agregar tanto a la anulación frontal como posterior y una mejor invalidación del iterador quevector
.deque
nunca se puede implementar por vector debido a su complejidad algorítmica y a las garantías de invalidación de iterador.¿Cuánta sobrecarga de memoria está asociada? Bueno, sinceramente, es una pregunta un poco inútil. Los contenedores STL están diseñados para ser eficientes, y si replicaras su funcionalidad, terminarías con algo que funciona peor o en el mismo lugar nuevamente. Al conocer sus estructuras de datos subyacentes, puede conocer la sobrecarga de memoria que usan, dan o toman, y solo será más que eso por una buena razón, como la optimización de cadenas pequeñas.
fuente
std::string
lo hicieran en ese momento. No tiene que estar utilizando las últimas y mejores implementaciones de STL para eso. msdn.microsoft.com/en-us/library/22a9t119.aspx dice "Si se inserta un elemento en la parte delantera, todas las referencias siguen siendo válidas". No estoy seguro de cómo piensa implementar eso con un búfer circular, ya que necesitará cambiar el tamaño cuando se llene.Si esa es realmente su pregunta (que seguramente no es lo que dijo en el texto de su pregunta real, que terminó en 4 preguntas, ninguna de las cuales preguntaba dónde podría encontrar un recurso), entonces la respuesta es simplemente:
No hay uno
La mayoría de los programadores de C ++ no tienen que preocuparse demasiado por la sobrecarga de las estructuras de la biblioteca estándar, el rendimiento de la caché de ellas (que de todos modos depende mucho del compilador) o ese tipo de cosas. Sin mencionar que, por lo general, no puede elegir la implementación de la biblioteca estándar; usa lo que viene con su compilador. Entonces, incluso si hace algunas cosas desagradables, las opciones de alternativas son limitadas.
Por supuesto, hay programadores que se preocupan por este tipo de cosas. Pero todos renunciaron a usar la biblioteca estándar hace mucho tiempo.
Entonces tienes un grupo de programadores a los que simplemente no les importa. Y otro grupo de programadores a los que les importaría si lo estuvieran usando, pero como no lo están usando, no les importa. Como a nadie le importa, no hay información real sobre este tipo de cosas. Hay parches informales de información aquí y allá (Effective C ++ tiene una sección sobre implementaciones std :: string y las grandes diferencias entre ellos), pero nada exhaustivo. Y ciertamente, nada se mantiene actualizado.
fuente