Brainer løsning: WinCE .NET compact framework er svært

tors aug 26, 2010 (Rolf)

Vores sidste brainer med .NET var for svær. Okay – det tog også lidt tid her at finde svaret, men det er der. Og mange andre vigtige ting, hvis man vil bruge .NET compact framework til systemer, som skal have en eller anden form for performance :-)

Men vi slipper ikke uden om at skulle give en løsning.

Sagen er den at foreach bruger en IEnumerator til at iterere over listen. For hvert loop foretages to kald til virtuelle metoder: IEnumerator.get_Current og IEnumerator.MoveNext.

Hvis man i stedet bruger en integer som index, vil man i loopen kunne nøjes med et enkelt virtuelt kald, nemlig ArrayList.get_Item(int index). Eftersom virtuelle kald er forholdsvis dyre, vil man derfor kunne observere en betydelig performance forskel.

Nedenstående kode viser et eksempel på hvordan man kan måle performance forskellen. Målinger foretaget i en simulator viser at første metode tager ca. 25 ms, hvorimod den optimerede udgave kan nøjes med 6,6 ms – en besparelse på godt 70%. Gennemsnittet er beregnet på et rundt antal målinger, i dette tilfælde otte.

Læg i øvrigt mærke til at Count gemmes i en lokal variabel umiddelbar før den sidste sløjfe. Eftersom compileren ikke kan gennemskue at Count er konstant mens sløjfen eksekveres, følgelig vil den kalde ArrayList.get_Count() for hvert loop – med degradering af performance til følge

[DllImport("coredll.dll")]
public static extern UInt32 GetTickCount();

public void TestPerformance()
{
   System.Collections.ArrayList a =
      new System.Collections.ArrayList(10000);

   // Fill arraylist with something simple
   for (int i = 0; i < a.Capacity; ++i)
   {
      a.Add(i);
   }

   // Use IEnumerator
   int sum1 = 0;
   UInt32 TStart = GetTickCount();
   foreach (int n in a)
      sum1 += n;
   UInt32 t1 = GetTickCount() - TStart;

   // Use integer indexer
   int sum2 = 0;
   TStart = GetTickCount();
   int Count = a.Count;
   for(int i=0; i<Count; ++i)
      sum2 += (int) a[i];
   UInt32 t2 = GetTickCount() - TStart;

   MessageBox.Show(string.Format("t1={0} ms, t2={1} ms, sums={2} and {3}", t1, t2, sum1, sum2));
}

Der er en lang forklaring på det her og mange andre vigtige forhold i en ppt fra Microsoft. god fornøjelse :-)

Hvad mener du?