Claudio Caldato - Perfromance & Garbage Collector PM
Seconda sessione Whiteboard, stimolante :-D, queste sono le domande poste dal pubblico:
Intrusiviness of the GC
Ho già parlato delle novità, che lo stesso Claudio ci ha introdotto, nella gestione del GC che Orcas porterà, adesso ci sta facendo vedere l'API:
GCSetting.LatencyMode = GCLatencyMode.Batch | Interactive | LowLatency;
Batch: StopEE --> Collection --> RestartEE uguale a quello che oggi è "GCConcurrency Off";
Interactive: molti StotEE --> Collection --> RestartEE ma di brevissima durata al fine di massimizzare l'interattività uguale a quello che oggi è "GCConcurrency On";
LowLatency: Chiede al GC di intervenire molto più spesso ma cercando di impattare il meno possibile sulle performance dell'intera applicazione, questo porterà il GC probabilmente a non fare tutto il lavoro che si era prefissato ma ci restituisce il controllo nel più breve tempo possibile;
GC.Collect( generation, [Default | Force | Optimized] );
la novità è Opmized che lascia decidere al GC se sia effettivamente il caso di fare una Collection o meno.
Generics Performance
Non ci sono note particolare sulle performance legate ai Generics, i Generics potrebbero impattare su NGen e venir comunque jittati nel caso in cui il tipo non sia noto.
Reflection
Non è una "bad pratice" ma è una "expensive pratice", quindi è da dosare e usare con le pinze. Un ottimo trucco per velocizzare le operazioni nel caso di chiamate multiple (in un ciclo ad esempio) ad un metodo sullo stesso tipo è quello di ricavare il MethodRuntimeHandle dalla classe (MethodBase.MethodHandle) e quindi recuperare un riferimento al metodo all'interno del ciclo tramite il metodo MethodBase.GetMethodFromHandle(), questa caching dell'handle ci permette di evitare che reflection faccia tutte le volte tutta l'analisi del grafo alla ricerca di quello che ci serve compreso l'eventuale overhead della CAS.
Finalization
Il Dispose pattern, non aggiungo altro ci sono montagne di articoli al riguardo...
Multi Threading
Anche qui le solite cose che tutti dovremmo sapere a menadito: non suare Thread.Abort(), usare il ThreadPool, non usare Thread.Suspend() ma sistemi più sofisticati tipo locking, mutex, semafori etc..
NGen
Fondamentale che NGen venga eseguito sulla macchina di destinazione.
benefits:
- non c'è jitting durante lo startup;
- sharing: il codcie NGened è condivisibile attraverso più processi, ad esempio un assembly viene condiviso su più processi, uno scenario particolarmente adatto è l'uso di un applicazione via RDC;
Interessante è la possibilità di usare un sevizio per "NGennare" in background l'applicazione
Marshaling Performances, P/Invoke
La prima cosa da controllare è che ci siano il minor numero di roundtrip tra codice managed e codice unmanaged, è inoltre fondamentale usare un profiler per tracciare l'uso della memoria... è appena intervenuto Raff con una soluzione ad un problema... giustamente non ho capito... Raff troppo avanti! :-D
nel fx 2.0 è stato fatto un lavoro notevole per ottimizzare il marshaling dei dati e Claudio ci conferma che per i tipi di dati semplici le performance sono molto buone, quello a cui dobbiamo porre molta attenzione è il passaggio di strutture molto complesse.
Rebasing
L'uso di NGen fa si che l'assembly venga convertito in codice nativo e gli viene assegnato un base address, se durante il loading dell'assembly in quell'indirizzo in memoria c'è già qualcosa l'assembly deve essere rebased e si perdono tutti i benefici di NGen, un workaround è quello di impostare il base address direttamente in fase di compilazione, ma resta comunque un terno al lotto ;-)
.m