windows - tiembla - Comparando el arranque en frío con el arranque en caliente
porque le cuesta arrancar a mi coche diesel (10)
¿Cómo perfiló su código? No todos los métodos de creación de perfiles son iguales y algunos encuentran los puntos de conexión mejores que otros. ¿Estás cargando muchos archivos? Si es así, la fragmentación del disco y el tiempo de búsqueda podrían entrar en juego.
Tal vez incluso incluir la información básica de sincronización en el código y escribir en un archivo de registro y examinar los archivos en frío / inicio cálido ayudará a identificar dónde está gastando su tiempo la aplicación.
Sin más información, me inclinaría hacia el sistema de archivos / caché de disco como la diferencia probable entre los dos entornos. Si ese es el caso, entonces debe pasar menos tiempo cargando archivos por adelantado, o encontrar formas más rápidas de cargar archivos. Un ejemplo (que puede no aplicarse) es que si está cargando la carga de archivos de datos binarios es combinarlos todos en un solo archivo, haga una slerp de todo el archivo en la memoria en una sola lectura, y luego analice sus contenidos. Menos sesiones de disco y tiempo dedicado a la lectura fuera del disco. De nuevo, quizás eso no se aplica. No conozco ninguna herramienta para borrar el disco / caché del sistema de archivos, pero podrías escribir una aplicación rápida para leer un montón de archivos no relacionados fuera del disco para provocar que el sistema de archivos / caché del disco se cargue con información diferente.
Nuestra aplicación tarda mucho más tiempo en iniciarse después de un reinicio (arranque en frío) que si ya se hubiera abierto una vez (inicio en caliente).
La mayoría (si no todos) la diferencia parece provenir de cargar archivos DLL, cuando los archivos DLL se encuentran en páginas de memoria en caché, se cargan mucho más rápido. Intentamos usar ClearMem para simular el reinicio (ya que consume mucho menos tiempo que en realidad reiniciar) y obtuvimos resultados mixtos, en algunas máquinas parecía simular un reinicio de manera consistente y en algunas no.
Para resumir mis preguntas son:
- ¿Has experimentado diferencias en el tiempo de lanzamiento entre inicios fríos y templados?
- ¿Cómo has perdido esas diferencias?
- ¿Conoces una forma de simular de manera confiable un reinicio?
Editar:
Aclaraciones para comentarios:
- La aplicación es principalmente C ++ nativa con algunos .NET (el primer ensamblado .NET que se carga paga por el CLR).
- Estamos buscando mejorar el tiempo de carga, obviamente, hicimos nuestra parte de perfiles y mejoramos los puntos de acceso en nuestro código.
Algo que olvidé mencionar es que obtuvimos alguna mejora volviendo a basar todos nuestros binarios para que el cargador no tenga que hacerlo en el momento de la carga.
En cuanto a la simulación de reinicios, ¿ha considerado ejecutar su aplicación desde una PC virtual ? Al usar la virtualización, puede replicar convenientemente un conjunto de condiciones una y otra vez.
También consideraría algún tipo de aplicación de creación de perfiles para detectar el fragmento de código que causa el retraso de tiempo, y luego hacer una estimación sobre cuánto de ese código es realmente necesario o si podría lograrse de una manera diferente.
Podrían ser los NIC (Tarjetas LAN) y su aplicación depende de ciertos otros servicios que requieren que la red aparezca. Por lo tanto, es posible que el perfil de su aplicación por sí solo no le diga esto, pero debe examinar las dependencias de su aplicación.
Sería difícil simular verdaderamente un reinicio en el software. Cuando reinicia, todos los dispositivos en su máquina obtienen su bit de reinicio afirmado, lo que debería causar la pérdida de toda la memoria de todo el sistema.
En una máquina moderna, tienes memoria y cachés en todas partes: está el subsistema VM que almacena páginas de memoria para el programa, luego tienes el sistema operativo almacenando el contenido de los archivos en la memoria caché, luego tienes el buffer de disco de sectores en el disco duro mismo. Probablemente pueda restaurar los cachés del sistema operativo, pero ¿el búfer en el disco de la unidad? No sé de una manera.
Una forma de hacer que las aplicaciones comiencen el arranque en frío más rápido (más o menos) es utilizado, por ejemplo, por Adobe Reader, cargando algunos de los archivos al inicio, ocultando así el inicio en frío de los usuarios. Esto solo se puede usar si el programa no debe iniciarse de inmediato.
Otra nota, es que .NET 3.5SP1 supuestamente ha mejorado mucho la velocidad de arranque en frío, aunque no puedo decir cuánto.
Una forma exitosa de acelerar el inicio de la aplicación es cambiar los archivos DLL para retrasar la carga. Este es un cambio de bajo costo (algunos cambios en la configuración del proyecto) pero puede hacer que el arranque sea mucho más rápido. Después, ejecute depends.exe en el modo de creación de perfiles para averiguar qué DLL se cargan durante el inicio de todos modos, y revertir el retraso de carga en ellos. Recuerde que también puede demorar la carga de la mayoría de las DLL de Windows que necesita.
Una técnica muy efectiva para mejorar el tiempo de lanzamiento en frío de la aplicación es optimizar el orden de enlace de función.
El enlazador de Visual Studio le permite pasar en un archivo una lista de todas las funciones en el módulo que está siendo enlazado (o solo algunas de ellas, no tiene que ser todas), y el enlazador ubicará esas funciones una al lado de la otra en memoria.
Cuando la aplicación se está iniciando, normalmente hay llamadas a funciones de inicio en toda la aplicación. Muchas de estas llamadas se realizarán en una página que aún no está en la memoria, lo que provocará un error de página y una búsqueda de disco. De ahí viene el inicio lento.
Optimizar su aplicación para que todas estas funciones estén juntas puede ser una gran victoria.
Consulte Optimización guiada de perfil en Visual Studio 2005 o posterior. Una de las cosas que PGO hace por usted es ordenar enlaces de función.
Es un poco difícil trabajar en un proceso de compilación, porque con PGO necesita vincular, ejecutar su aplicación y luego volver a vincularse con el resultado de la ejecución del perfil. Esto significa que su proceso de compilación necesita tener un entorno de tiempo de ejecución y hacer frente a la limpieza después de compilaciones incorrectas y todo eso, pero el rendimiento suele ser 10 o más veces más rápido y sin cambios de código.
Hay más información sobre PGO aquí:
Como alternativa a la lista de orden de funciones, simplemente agrupe el código que será llamado dentro de las mismas secciones:
#pragma code_seg(".startUp")
//...
#pragma code_seg
#pragma data_seg(".startUp")
//...
#pragma data_seg
Debe ser fácil de mantener a medida que cambia el código, pero tiene el mismo beneficio que la lista de orden de funciones.
No estoy seguro de si la lista de orden de funciones también puede especificar variables globales, pero use este #pragma data_seg simplemente funcionaría.
Si su aplicación no es muy complicada, puede simplemente copiar todos los ejecutables a otro directorio, debería ser similar a un reinicio. (Cortar y pegar parece que no funciona, Windows es lo suficientemente inteligente como para saber que los archivos que se mueven a otra carpeta se almacenan en la memoria)
@ Morten Christiansen dijo:
Una forma de hacer que las aplicaciones comiencen el arranque en frío más rápido (más o menos) es utilizado, por ejemplo, en Adobe Reader, cargando algunos de los archivos al inicio, ocultando así el inicio en frío de los usuarios. Esto solo se puede usar si el programa no debe iniciarse de inmediato.
Eso hace que el cliente pague por inicializar nuestra aplicación en cada arranque, incluso cuando no se utiliza, realmente no me gusta esa opción (tampoco lo hace Raymond ).