Questo blog-entry é stato ricavato da una mail interna in cui spiegavo a dei colleghi di CA che stanno lavorando su Silverlight 4.0 come ho risolto un antipatico problema di prestazioni ed uso eccessivo del processore di una applicazione Silverlight 4.0. Ve la riporto pari pari
.... Ciao, avete presente la shell silverlight sulla quale stiamo
lavorando ? beh uno dei problemi era quello delle prestazioni e dello “strano”
utilizzo elevato del processore anche quando non si faceva nulla. Dopo aver un
po’ cercato su internet mi sono immediatamente imbattuto in due articoli che
spiegano come abilitare il profiling per applicazioni Silverlight, cosa non
supportata ufficialmente o “out of the box” apparentemente con vs2010. Oltre a
leggere gli articoli ho dovuto smanettare veramente poco a causa del mio sistema
a 64 bit.
Quindi ... grazie a questo articolo:
http://blogs.msdn.com/askie/archive/2009/03/09/opening-a-new-tab-may-launch-a-new-process-with-internet-explorer-8-0.aspx
e questo per preparare il browser internet opportunamente
per la gestione dei processi
http://blogs.msdn.com/mgoldin/archive/2010/04/26/vs2010-silverlight-4-profiling.aspx
ho beccato dopo una sessione di profile questo giro
nell’applicazione aprendo il file di profiling direttamente dentro vs2010 con
Open File (doppio click da shell/explorer non funziona):
”
Osservate cosa fa vstudio 2010 se cliccate sul link di cui
sopra:
Apre il sorgente e aggiunge una carinissima icona che mostra
il punto incriminato con un bel fuocherello:
L’istruzione di sincronizzazione della sezione critica é
assolutamente incolpevole. Seguendo il call-stack scopro che la colpa é di chi la chiama in modo esagerato da un ciclo for-ever, causa reale del problema. Con un piccolo walk dello stack e grazie
al profiler e le sue indicazioni sono arrivato nella funzione di cui sotto.
Sostanzialmente la sleep per fare un po’ di “yielding” (termine inadatto: non é
multiprogrammazione peró fa respirare gli altri processi lo stesso) é nel posto
sbagliato !!!!!
... Commentandola (in rosso) e spostandola fuori dal blocco THEN (in
giallo) dell’IF il problema é risolto in un attimo e l’applicazione passa dal
25% (sul mio quad-core !!!!) a 0% a beneficio delle animazioni ecc.
/// <summary>
///
Occurs when worker is
runned.
/// </summary>
/// <param name="sender"></param>
/// <param name="Argument"></param>
protected override
void OnRun(AsyncWorker<object>
sender, object Argument)
{
base.OnRun(sender, Argument);
bool terminationCondition = false;
lock (this.SyncForceTermination)
{
terminationCondition = this.ForceTermination;
}
while ( ! terminationCondition )
{
TTask task = default(TTask);
lock (this.SyncTasks)
{
if (this.Taks.Count
>
0)
{
task = this.Taks.Dequeue();
}
}
if (task != null)
{
TTaskManagerJob job = default(TTaskManagerJob);
if (task.TaskType == TaskType.None)
{
job = BuildJobContext(new Object[] { task });
}
else
{
job = (TTaskManagerJob)BuildJobContext(this.GetTaskType(task),
new Object[]
{ task });
}
job.OnTermination -= new EventHandler<WorkerJobEventArgs<TTask>>(Job_OnTermination);
job.OnTermination += new
EventHandler<WorkerJobEventArgs<TTask>>(Job_OnTermination);
ThreadPool.QueueUserWorkItem(job.Execute);
//
Thread.Sleep(100); // =DG= rimosso per performance
lock (this.SyncForceTermination)
{
terminationCondition = this.ForceTermination;
}
}
Thread.Sleep(100); // =DG= aggiunto
per performance
}
}
|
Giuseppe