Pregunta

¿Hay razones de peso para elegir rendimiento vinculación estática sobre la vinculación dinámica o viceversa en ciertas situaciones? He escuchado o leído lo siguiente, pero no sé lo suficiente sobre el tema para dar fe de su veracidad.

1) La diferencia en el rendimiento de tiempo de ejecución entre la vinculación estática y la vinculación dinámica es generalmente despreciable.

2) (1) no es cierto si se utiliza un compilador de perfiles que los datos del perfil usos a hotpaths programa a optimizar ya que con la vinculación estática, el compilador puede optimizar tanto su código y el código de la biblioteca. Con la vinculación dinámica solamente su código puede ser optimizado. Si la mayor parte del tiempo se dedica a la ejecución de código de biblioteca, esto puede hacer una gran diferencia. De lo contrario, (1) sigue siendo válida.

¿Fue útil?

Solución

  • Dynamic de enlace puede reducir el consumo total de recursos (si las acciones más de un proceso de la misma biblioteca (incluyendo la versión en "la misma", por supuesto)). Creo que este es el argumento que lo impulsa su presencia en la mayoría de los entornos. Aquí "recursos" incluyen espacio en disco, memoria RAM y espacio de caché. Por supuesto, si su enlazador dinámico no es lo suficientemente flexible, existe el riesgo de DLL infierno .
  • dinámico medios de unión que correcciones de errores y mejoras a las bibliotecas propagan para mejorar su de productos sin necesidad de enviar nada.
  • plugins siempre llame para dinámico vincular.
  • estático vincular, significa que puede saber el código se ejecutará en muy entornos limitados (al principio del proceso de arranque, o en modo de rescate).
  • estático vincular puede hacer binarios más fáciles de distribuir a diversos entornos de usuario (en el costo de envío de una mayor y más recursos del programa hambre).
  • estático vinculación puede permitir ligeramente más rápido de inicio veces, pero esto depende en cierta medida de tanto el tamaño y la complejidad de su programa y en los detalles de la estrategia de carga del sistema operativo.

Algunos edita para incluir las sugerencias muy relevantes en los comentarios y en otras respuestas. Me gustaría señalar que la forma se rompe en este depende mucho de qué entorno va a ejecutar en. Minimal sistemas embebidos pueden no tener los recursos suficientes a la vinculación de soporte dinámico. Ligeramente pequeños sistemas más grandes pueden también soportan la vinculación dinámica, porque su memoria es lo suficientemente pequeño como para que el ahorro de RAM dinámica que unen muy atractivo. El estallido de los PC de consumo tienen, como señala Mark, enormes recursos, y es probable que pueda dejar que las cuestiones de conveniencia conducir su pensamiento sobre este asunto.


Para hacer frente a los problemas de rendimiento y eficiencia:. depende

Clásicamente, las bibliotecas dinámicas requiere una cierta clase de capa de cola que a menudo significa el doble de despacho o una capa extra de indirección en función de direccionamiento y puede costar un poco de velocidad (pero se llama a la función de tiempo en realidad una gran parte de su tiempo de funcionamiento ?? ?).

Sin embargo, si está ejecutando varios procesos que todas las llamadas de la misma biblioteca mucho, se puede llegar a ahorrar líneas de caché (y ganando así el rendimiento de la carrera) al utilizar la vinculación dinámica en relación con el uso de la vinculación estática. (A menos modernos sistemas operativos son lo suficientemente inteligentes como para notar segmentos idénticos en los binarios enlazados estáticamente. Parece difícil, Alguien sabe?)

Otra cuestión: el tiempo de carga. Que asumirá la carga de los costos en algún momento. Cuando se paga este costo depende de cómo el sistema operativo funciona tan bien como lo que une que utilice. Tal vez prefiere aplazar el pago hasta que sepa que lo necesite.

Tenga en cuenta que la vinculación estática-vs-dinámica es tradicionalmente no un problema de optimización, ya que ambas implican la compilación separada a los ficheros objeto. Sin embargo, esto no es necesario: una lata compilador, en principio, "compilación" "bibliotecas estáticas" a una forma AST digerido inicialmente, y "enlace" mediante la adición de esos AST a los generados por el código principal, potenciando así la optimización global. Ninguno de los sistemas que utilizo hacer esto, así que no puedo comentar sobre lo bien que funciona.

La forma de preguntas de desempeño respuesta es siempre probando (y el uso de un entorno de prueba tanto como el entorno de despliegue de lo posible).

Otros consejos

1) se basa en el hecho de que llamar a una función DLL siempre está utilizando un salto indirecto adicional. Hoy en día, esto es generalmente insignificante. Dentro de la DLL hay algo de más sobrecarga en i386 de la CPU, ya que no pueden generar código independiente de posición. En amd64, puede haber saltos en relación con el contador de programa, por lo que esta es una gran mejora.

2) Esto es correcto. Con optimizaciones guiadas por perfiles que normalmente se puede ganar alrededor del 10-15 por ciento de rendimiento. Ahora que la velocidad de la CPU ha llegado a su límite podría valer la pena hacerlo.

I añadiría: (3) el enlazador puede organizar funciones en una memoria caché agrupación más eficiente, de modo que se pierde caros nivel de caché se reducen al mínimo. También podría afectar especialmente el tiempo de inicio de aplicaciones (en base a los resultados que he visto con el compilador C ++ Sol)

Y no hay que olvidar que la DLL no es de eliminación de código muerto se puede realizar. Dependiendo del idioma, el código DLL podría no ser óptima tampoco. funciones virtuales son siempre virtual, porque el compilador no sabe si un cliente es sobrescribir la misma.

Por estas razones, en caso de que no existe una necesidad real de DLL, a continuación, sólo tiene que utilizar la compilación estática.

Edit (para contestar el comentario, por un guión de usuario)

Aquí es un recurso bien acerca de la posición independiente de problemas de código http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

Como se explica x86 no les tiene que yo sepa para cualquier otra cosa, entonces los rangos de salto de 15 bits y no por saltos incondicionales y llamadas. Es por eso que las funciones (de generadores) que tienen más de 32 K siempre han sido un problema y se necesitan camas elásticas embebidas.

Sin embargo, en el popular sistema operativo Linux x86 como que simplemente no tiene que preocuparse si el archivo SO / DLL no se genera con el interruptor de gcc -fpic (que impone el uso de las tablas de saltos indirectos). Porque si no lo hace, el código se acaba de arreglar como un enlazador normal sería reubicarlo. Pero al hacer esto hace que el segmento de código no compartible y que necesitaría un mapeo completo del código del disco a la memoria y tocando todo antes de que pueda ser utilizado (vaciado de la mayor parte de los cachés, golpeando de TLB), etc. Había una vez cuando esto se considera lento ... demasiado lento.

Así que no tendría ningún beneficio más.

no recuerdo qué sistema operativo (Solaris o FreeBSD) me dio problemas con mi sistema de construcción de Unix porque simplemente no estaba haciendo esto y se preguntó por qué se estrelló hasta que me presenté a -fPIC gcc.

Dinámica de enlace es la única forma práctica de cumplir con algunos requisitos de la licencia como el LGPL .

Estoy de acuerdo con los puntos dnmckee menciona, además de:

  • estáticamente vinculado aplicaciones podrían ser más fáciles de implementar, ya que no existen dependencias de archivos adicionales o menos (.dll / .so) que los problemas pueden provocar un error cuando están ausentes o instalados en el lugar equivocado.

Una de las razones para hacer una acumulación enlazado estáticamente es para comprobar que usted tiene el cierre total para el ejecutable, es decir, que todas las referencias a los símbolos se resuelven correctamente.

Como parte de un sistema grande que estaba siendo construido y probado usando la integración continua, las pruebas de regresión nocturnas se realizaron utilizando una versión enlazado estáticamente de los ejecutables. De vez en cuando, veríamos que un símbolo no resolvería y el enlace estática sería un fracaso a pesar de que el ejecutable enlazado dinámicamente enlazaría con éxito.

Esto fue por lo general ocurre cuando los símbolos que nos sentaron en lo profundo de las librerías compartidas tenían un nombre mal escrito y por lo tanto sería no estáticamente enlace. El enlazador dinámico no resuelve por completo todos los símbolos, con independencia de la utilización de primero en profundidad o en anchura de evaluación, por lo que puede terminar con un ejecutable enlazado dinámicamente que no tiene cierre total.

1 / he estado en proyectos donde se Benchmarked dinámico que une vs vinculación estática y la diferencia no fue determinado lo suficientemente pequeño como para cambiar a la vinculación dinámica (que no era parte de la prueba, sólo sé la conclusión)

2 / dinámico de unión se asocia a menudo con PIC (código independiente de posición, código que no necesita ser modificado en función de la dirección en la que se carga). Dependiendo de la arquitectura PIC puede traer a otra desaceleración pero se necesita con el fin de obtener beneficios de compartir una biblioteca de enlace dinámico entre dos ejecutable (e incluso dos procesos del mismo ejecutable si el uso del sistema operativo de la aleatorización dirección de carga como medida de seguridad). No estoy seguro de que todos los OS permiten separar los dos conceptos, pero Solaris y Linux hago y ISTR que HP-UX también lo hace.

3 / He estado en otros proyectos que utilizan la vinculación dinámica para la función "fácil de parche". Pero este "parche fácil" hace que la distribución de pequeño arreglo un poco más fácil y complicado de una pesadilla de versiones. A menudo terminamos por tener que empujar todo lo más el tener que realizar un seguimiento de los problemas en el sitio del cliente, porque la versión incorrecta fue testigo.

Mi conclusión es que había usado la vinculación estática exceptuado:

  • para cosas como complementos que dependen de la dinámica de enlace

  • Cuando se comparte es importante (grandes librerías utilizadas por varios procesos al mismo tiempo como el tiempo de ejecución de C / C ++, bibliotecas de interfaz gráfica de usuario, ... que a menudo se gestionan de forma independiente y para los que el ABI está estrictamente definidas)

Si se desea utilizar el "parche fácil", yo diría que las bibliotecas tienen que ser gestionados como los grandes bibliotecas anteriores: tienen que ser casi independiente con un ABI definido que no debe ser cambiada por correcciones <. / p>

Este discutir en detalle acerca de las bibliotecas compartidas en Linux y rendimiento implicaciones.

Es muy simple, realmente. Cuando se hace un cambio en el código fuente, ¿quieres que esperar 10 minutos para que se construyen o 20 segundos? Veinte segundos es todo lo que puedo soportar. Más allá de eso, ya sea salir de la espada o empezar a pensar en cómo puedo usar compilación separada y la vinculación a traer de vuelta a la zona de confort.

En los sistemas Unix, la vinculación dinámica puede hacer la vida difícil de 'root' para utilizar una aplicación con las bibliotecas compartidas instaladas en lugares fuera de la vía. Esto es debido a que el enlazador dinámico generalmente no prestará atención a LD_LIBRARY_PATH o su equivalente para procesos con privilegios de root. A veces, a continuación, la vinculación estática salva el día.

Por otra parte, el proceso de instalación tiene que localizar las bibliotecas, sino que puede hacer que sea difícil para varias versiones del software para coexistir en la máquina.

Enlazado dinámico requiere tiempo adicional para el sistema operativo para encontrar la biblioteca dinámica y cargarlo. Con la vinculación estática, todo es en conjunto y es una carga de una sola vez en la memoria.

También, ver DLL Infierno . Este es el escenario en el que la DLL que cargue el sistema operativo no es el que vino con el producto, o la versión de que sus Espera aplicación.

Best ejemplo para la vinculación dinámica es, cuando la biblioteca es dependiente del hardware usado. En la antigüedad, la biblioteca C matemáticas se decidió a ser dinámico, de modo que cada plataforma puede utilizar todas las capacidades del procesador para optimizarlo.

Una mejor ejemplo podría ser OpenGL. OpenGL es una API que se implementa de forma diferente por AMD y NVidia. Y usted no es capaz de utilizar una implementación NVidia en una tarjeta de AMD, ya que el hardware es diferente. No se puede vincular OpenGL estáticamente en su programa, porque de eso. La vinculación dinámica se utiliza aquí para que la API se ha optimizado para todas las plataformas.

Otro asunto discutido aún no está corrigiendo errores en la biblioteca.

Con la vinculación estática, que no sólo tienen que reconstruir la biblioteca, pero tendrá que volver a vincular y redestribute el ejecutable. Si la biblioteca es sólo utilizado en un ejecutable, esto puede no ser un problema. Pero los más ejecutables que necesitan ser Relinked y redistribuido, cuanto más grande es el dolor.

Con la vinculación dinámica, que acaba de reconstruir y redistribuir la biblioteca dinámica y ya está.

enlazado estático le da un solo exe, a finde para hacer un cambio que necesita recompilar todo su programa. Mientras que en la vinculación dinámica que necesita para hacer el cambio sólo a la DLL y cuando se ejecuta el exe, los cambios le recogerá en runtime.Its más fácil para proporcionar actualizaciones y correcciones de errores de dinámica de enlace. (Por ejemplo: ventanas)

Hay un gran y creciente número de sistemas en los que un nivel extremo de vinculación estática puede tener un enorme impacto positivo en las aplicaciones y el rendimiento del sistema.

Me refiero a lo que a menudo son llamados "sistemas integrados", muchos de los cuales están ahora utilizando cada vez más los sistemas operativos de propósito general, y de estos sistemas se utilizan para todo lo imaginable.

Un ejemplo muy común son los dispositivos que utilizan sistemas GNU / Linux usando Busybox . Me he tomado esto al extremo con NetBSD (32 bits) imagen del sistema que la construcción de un arranque i386 incluye tanto un núcleo y su sistema de ficheros raíz, este último, que contiene un binario sola estática ligado (por crunchgen) con enlaces duros a todos los programas que sí contiene todos (bien en el último recuento 274) del los programas del sistema con todas las características estándar (la mayoría, excepto la cadena de herramientas), y que está a menos de 20 Mega bytes de tamaño (y, probablemente, corre muy cómodamente en un sistema con solamente 64 MB de memoria (incluso con el sistema de ficheros raíz sin comprimir y enteramente en RAM), aunque no he podido encontrar uno tan pequeño probarlo en).

Se ha mencionado en críticas anteriores que el tiempo de puesta en marcha de un binarios estáticos ligado es más rápido (y que puede ser un mucho más rápido), pero eso es sólo una parte de la imagen, especialmente cuando todo el código objeto está vinculado en el mismo archivo, y aún más especialmente cuando los soportes del sistema operativo exigen paginación de código directamente desde el archivo ejecutable. En este escenario ideal, el tiempo de inicio de los programas es literalmente insignificante ya que casi todas las páginas de código ya estarán en la memoria y en uso por el shell (yy init cualesquiera otros procesos de fondo que podrían estar en ejecución) , incluso si el programa solicitado alguna vez no se ha ejecutado desde el arranque ya que tal vez sólo una página de la memoria tiene que ser cargado para cumplir con los requisitos de tiempo de ejecución del programa.

Sin embargo eso no es todavía toda la historia. También suelen construir y utilizar las instalaciones del sistema operativo NetBSD para mis sistemas completos de desarrollo de la electricidad estática que une todos los binarios. A pesar de que esto se lleva a una enorme cantidad más espacio en disco (~ 6.6GB total para x86_64 con todo, incluyendo la cadena de herramientas y X11 estática ligado) (sobre todo si se tiene tablas de símbolos de depuración completa para todos los programas de otra ~ 2.5GB), el resultado sigue siendo corre más rápido en general, y para algunas tareas, incluso utiliza menos memoria que un típico sistema dinámico ligado que pretende compartir las páginas de código de biblioteca. Disco es barato (incluso disco rápido), y la memoria de caché utilizado con frecuencia archivos de disco también es relativamente barato, pero los ciclos de CPU realmente no lo son, y pagar el costo de inicio ld.so para cada proceso que se inicia cada Hora aperturas tendrán horas y horas de ciclos de CPU lejos de las tareas que requieren iniciar muchos procesos, especialmente cuando se utilizan los mismos programas una y otra vez, como compiladores de un sistema de desarrollo. Estática ligada cadena de herramientas programas pueden reducir toda-OS veces multi-arquitectura de construcción para mis sistemas por horas . Todavía tengo que construir la cadena de herramientas en mi única binaria crunchgen'ed, pero sospecho que cuando lo haga, habrá más horas de tiempo de construcción salvado debido a la victoria para el caché de la CPU.

vinculación estática incluye los archivos que las necesidades de los programas en un único archivo ejecutable.

Dinámica de enlace es lo que se consideraría la habitual, se hace un ejecutable que todavía requiere DLLs y como estar en el mismo directorio (o los archivos DLL podrían estar en la carpeta del sistema).

(DLL = enlace dinámico biblioteca)

ejecutables enlazadas dinámicamente se compilaron más rápido y no son tan pesadas de recursos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top