Domanda

La nostra applicazione impiega molto più tempo ad avviarsi dopo un riavvio (avvio a freddo) rispetto a se fosse già stata aperta una volta (avvio a caldo).

La maggior parte (se non tutte) la differenza sembra derivare dal caricamento delle DLL, quando le DLL si trovano nelle pagine di memoria memorizzate nella cache, si caricano molto più velocemente. Abbiamo provato a utilizzare ClearMem per simulare il riavvio (poiché richiede molto meno tempo rispetto al riavvio effettivo) e ottenuto risultati contrastanti, su alcune macchine sembrava simulare un riavvio in modo molto coerente e in alcuni no.

Per riassumere le mie domande sono:

  1. Hai riscontrato differenze nei tempi di avvio tra avviamenti a freddo e a caldo?
  2. Come hai approfondito queste differenze?
  3. Conosci un modo per simulare in modo affidabile un riavvio?

Modifica

Chiarimenti per i commenti:

  • L'applicazione è principalmente C ++ nativa con alcuni .NET (il primo assembly .NET caricato paga per il CLR).
  • Stiamo cercando di migliorare i tempi di caricamento, ovviamente abbiamo fatto la nostra parte di profilazione e migliorato gli hotspot nel nostro codice.

Qualcosa che ho dimenticato di menzionare è che abbiamo ottenuto qualche miglioramento ri-basando tutti i nostri binari in modo che il caricatore non debba farlo al momento del caricamento.

È stato utile?

Soluzione

Come hai profilato il tuo codice? Non tutti i metodi di profilazione sono uguali e alcuni trovano gli hotspot migliori di altri. Stai caricando molti file? In tal caso, potrebbe entrare in gioco la frammentazione del disco e il tempo di ricerca.

Forse persino inserire le informazioni di base nel timing, scrivere in un file di registro ed esaminare i file all'avvio a freddo / a caldo aiuterà a identificare dove l'app sta trascorrendo del tempo.

Senza ulteriori informazioni, mi spingerei verso la cache del filesystem / disco come la probabile differenza tra i due ambienti. In tal caso, dovrai trascorrere meno tempo a caricare i file in anticipo o trovare modi più veloci per caricare i file.

Esempio: se stai caricando molti file binari di dati, velocizza il caricamento combinandoli in un singolo file, quindi esegui uno slerp dell'intero file in memoria in una lettura e analizzane il contenuto. Meno ricerche su disco e tempo impiegato a leggere il disco. Ancora una volta, forse non si applica.

Non conosco con disinvoltura alcuno strumento per cancellare la cache del disco / filesystem, ma potresti scrivere una rapida applicazione per leggere un mucchio di file non correlati dal disco per far caricare il filesystem / la cache del disco con informazioni diverse .

Altri suggerimenti

Per quanto riguarda la simulazione di riavvii, hai preso in considerazione la possibilità di eseguire la tua app da un PC virtuale ? Utilizzando la virtualizzazione è possibile replicare comodamente una serie di condizioni più e più volte.

Vorrei anche prendere in considerazione un tipo di app di profilazione per individuare il bit di codice che causa il tempo ritardare e quindi fare in modo che il giudizio richieda quanto di quel codice è veramente necessario o se potrebbe essere ottenuto in modo diverso.

Sarebbe difficile simulare veramente un riavvio nel software. Quando riavvii, tutti i dispositivi nel tuo computer ottengono il loro bit di ripristino, il che dovrebbe causare la perdita di tutta la memoria a livello di sistema.

In una macchina moderna hai memoria e cache ovunque: c'è il sottosistema VM che memorizza pagine di memoria per il programma, quindi hai il sistema operativo che memorizza nella cache il contenuto dei file, quindi hai il buffer su disco dei settori sul disco rigido stesso. Probabilmente è possibile ripristinare le cache del sistema operativo, ma il buffer su disco sull'unità? Non conosco un modo.

@ Morten Christiansen ha detto:

  

Un modo per fare in modo che le app si avviano a freddo (più o meno) è usato ad es. Adobe Reader, caricando alcuni dei file all'avvio, nascondendo così l'avvio a freddo da parte degli utenti. Questo è utilizzabile solo se il programma non dovrebbe avviarsi immediatamente.

Questo fa pagare al cliente l'inizializzazione della nostra app ad ogni avvio anche quando non viene utilizzata, in realtà non mi piace quell'opzione (né Raymond ).

Un modo efficace per accelerare l'avvio dell'applicazione è quello di passare alle DLL per ritardare il caricamento. Si tratta di una modifica a basso costo (alcuni con armeggi con le impostazioni del progetto) ma può rendere l'avvio molto più veloce. Successivamente, esegui depend.exe in modalità di profilatura per capire quali DLL caricare all'avvio in ogni caso e ripristinare il caricamento ritardato su di esse. Ricorda che potresti anche ritardare il caricamento della maggior parte delle DLL di Windows necessarie.

Una tecnica molto efficace per migliorare i tempi di avvio a freddo delle applicazioni è l'ottimizzazione dell'ordinamento dei collegamenti delle funzioni.

Il linker di Visual Studio ti consente di passare in un elenco di file tutte le funzioni del modulo da collegare (o solo alcune di esse - non deve essere tutte) e il linker posizionerà tali funzioni accanto a l'un l'altro in memoria.

All'avvio dell'applicazione, in genere vi sono chiamate a funzioni init in tutta l'applicazione. Molte di queste chiamate saranno indirizzate a una pagina che non è ancora in memoria, causando un errore di pagina e una ricerca del disco. Ecco da dove viene l'avvio lento.

L'ottimizzazione dell'applicazione in modo che tutte queste funzioni siano unite può essere una grande vittoria.

Scopri l'ottimizzazione guidata del profilo in Visual Studio 2005 o versioni successive. Una delle cose che PGO fa per te è l'ordinamento di link di funzioni.

È un po 'difficile lavorare in un processo di compilazione, perché con PGO è necessario collegare, eseguire l'applicazione e quindi ricollegare con l'output dall'esecuzione del profilo. Ciò significa che il tuo processo di compilazione deve avere un ambiente di runtime e gestire la pulizia dopo build errate e tutto il resto, ma il payoff è in genere 10+ o più veloce avvio a freddo senza modifiche al codice.

Ci sono altre informazioni su PGO qui:

http://msdn.microsoft.com/en-us/library /e7k32f4k.aspx

In alternativa all'elenco degli ordini di funzioni, basta raggruppare il codice che verrà chiamato all'interno delle stesse sezioni:

#pragma code_seg(".startUp")
 //...
#pragma code_seg

#pragma data_seg(".startUp")
 //...
#pragma data_seg

Dovrebbe essere facile da mantenere quando il codice cambia, ma ha gli stessi vantaggi dell'elenco degli ordini delle funzioni.

Non sono sicuro che anche l'elenco degli ordini di funzioni possa specificare variabili globali, ma usare questo #pragma data_seg funzionerebbe semplicemente.

Un modo per fare in modo che le app si avviano a freddo (più o meno) è usato ad es. Adobe Reader, caricando alcuni dei file all'avvio, nascondendo così l'avvio a freddo da parte degli utenti. Questo è utilizzabile solo se il programma non dovrebbe avviarsi immediatamente.

Un'altra nota è che .NET 3.5SP1 ha presumibilmente migliorato molto la velocità di avvio a freddo, anche se quanto, non posso dire.

Potrebbero essere le schede di rete (schede LAN) e la tua app dipende da alcune altre servizi che richiedono la creazione della rete. Quindi la profilazione della tua applicazione da sola potrebbe non dirti esattamente questo, ma dovresti esaminare le dipendenze per la tua applicazione.

Se la tua applicazione non è molto complicata, puoi semplicemente copiare tutti gli eseguibili in un'altra directory, dovrebbe essere simile a un riavvio. (Taglia e incolla sembra non funzionare, Windows è abbastanza intelligente da sapere che i file spostati in un'altra cartella sono memorizzati nella cache)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top