• No results found

VB.NET-versionen är algoritmmässigt exakt likadan som de båda andra men skiljer sig givetvis åt i syntaxen och visas därför i sin helhet här:

Sub FFT(ByVal data As Double(), ByVal N As Integer)

Dim length As Integer = 2 * N

Dim i As Integer = 0, j As Integer = 0

' Kasta om indatan i bitreverserad ordning

For i = 0 To length - 1 Step 2

If j > i Then

Dim temp As Double = data(j)

data(j) = data(i) data(i) = temp temp = data(j + 1) data(j + 1) = data(i + 1) data(i + 1) = temp End If Dim m As Integer = N While m > = 2 And j > = m j = j - m m = m / 2 End While j = j + m Next

' Utför beräkningarna med hjälp av Danielson-Lanczos lemma

Dim mmax As Integer = 2

While length > mmax

Dim istep As Integer = 2 * mmax

Dim theta As Double = -Math.PI / mmax Dim wtemp As Double = Math.Sin(0.5 * theta)

Dim wpr As Double = -2.0 * wtemp * wtemp Dim wpi As Double = Math.Sin(theta)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

VB

9.5. Jämförelse av de olika versionerna

Dim wr As Double = 1.0

Dim wi As Double = 0.0

Dim m As Integer

For m = 0 To mmax - 1 Step 2

For i = m To length - 1 Step istep j = i + mmax

Dim tempr As Double = wr * data(j) - wi * data(j + 1)

Dim tempi As Double = wr * data(j + 1) + wi * data(j)

data(j) = data(i) - tempr

data(j + 1) = data(i + 1) - tempi data(i) += tempr data(i + 1) += tempi Next wtemp = wr wr = wr * wpr - wi * wpi + wr wi = wi * wpr + wtemp * wpi + wi Next mmax = istep End While End Sub 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

VB

Av skillnaderna i detaljer kan man notera t ex att variablerna i och j måste deklareras för sig före for-satsen (rad 3). På rad 1 finns också en intressant skillnad i jämförelse med C#- versionen i och med att Shared (motsvarande static i C#) inte har använts. Istället utnyttjas VB:s modulkoncept för att placera funktionen i en modul istället för en klass. Funktionen blir dessutom automatiskt publik. Denna variant valdes enbart för att visa på denna möj- lighet när det aktuella problemet inte har någon nytta av objektorienteringen. Naturligtvis skulle man lika gärna kunna lägga dit Shared och placera funktionen inuti en klassdefini- tion.

9.5

Jämförelse av de olika versionerna

Som har framgått av beskrivningarna är det mycket små skillnader mellan språken i det här fallet. Bortsett från VB:s annorlunda syntax är det bara detaljer i objektorientering, deklara- tion av arrayer samt sättet att komma åt konstantenπoch sinusfunktionen som skiljer. Det är svårt att säga något annat än att versionerna är helt ekvivalenta i komplexitetshänseende. Däremot förväntar man sig skillnader i prestanda som framgår av avsnitt 11.3.

Kapitel 10

Applikationen Draw

I detta kapitel beskrivs de olika versionerna av applikationen Draw. Applikationen är im- plementerad som en Windowsapplikation där Visual C++-versionen är en dialogbaserad MFC-applikation och C#- och VB.NET-versionerna använder Windows Forms-klasserna i .NET FCL.

Användargränssnittet består av en enda knapp med texten Draw. När knappen klickas anropas en metod som utför linjeuppritningen. Den metoden kommer beskrivas här.

10.1

Visual C++-versionen

Här visas metoden som ritar upp linjerna:

void CDrawMFCDlg::OnBnClickedDraw()

{

CClientDC dc(this);

CPen* oldPen = dc.SelectObject(&CPen(PS_SOLID, 1, RGB(0, 0, 0)));

for (int i = 0; i < 500000; i++)

{

CPen pen(PS_SOLID, 1, RGB(random(256),

random(256), random(256)));

dc.SelectObject(&pen)->DeleteObject(); // Radera gamla pennan

int x1 = random(400); int y1 = random(400); int x2 = random(400); int y2 = random(400); dc.MoveTo(x1, y1); dc.LineTo(x2, y2); } dc.SelectObject(oldPen); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

C++

OnBnClickedDraw anropas när användaren klickar på Draw-knappen. För att rita i fönstret behövs ett objekt av en CDC-ärvd klass. På rad 3 skapas ett sådant av klassen CClientDC som medger ritande i fönstrets klientarea. Konstruktorn vill som argument ha en pekare

till aktuellt fönster, vilket i detta fall blir this eftersom OnBnClickedDraw är en metod i klassen som beskriver applikationens fönster (som ärver från CDialog som i sin tur ärver från CWnd).

På raderna 4–5 skapas ett nytt CPen-objekt som väljs in i DC:n. Detta görs här enbart för att få tillgång till den tidigare valda pennan så att den längre fram (på rad 22) kan återställas (se även avsnitt 7.1.4 på sid 55).

Inuti slingan skapas ett nytt CPen-objekt av slumpmässig färg. Att skapa ett nytt objekt är nödvändigt eftersom det inte går att byta färg på en existerande penna. Den slumpmäs- siga färgen fås med hjälp av RGB-makrot och en enkel hjälpmetod (kallad random) som använder standardfunktionen rand för att generera ett slumptal i önskad intervall. Med ar- gumentet 256 kommer den att returnera ett tal i intervallet [0, 255].

När den nya pennan väljs in i DC:n returneras en pekare till den tidigare, och meto- den DeleteObject anropas för att frigöra de resurser som den tidigare pennan använde. Om DeleteObject inte anropas kommer resurserna ändå frigöras när destruktorerna exekveras men eftersom det inte sker förrän tidigast när slingan är slut kan det bli problem i detta fall i och med att så många pennobjekt skapas. (Vid testningen verkade det fungera ändå i Win- dows XP, men i Windows ME slutade applikationen fungera efter ett visst antal uppritade linjer.)

På raderna 14–17 skapas fyra slumpmässiga tal som utgör koordinater till den linje som ritas upp på raderna 18 och 19 med hjälp av metoderna MoveTo och LineTo.

10.2

C#-versionen

Den metod i C#-versionen som utför linjeritningen ser ut som följer:

private void buttonDraw_Click(object sender, EventArgs e)

{

Graphics gfx = CreateGraphics();

Pen pen = new Pen(Color.Black);

Random rand = new Random();

for (int i = 0; i < 500000; i++)

{

pen.Color = Color.FromArgb(rand.Next(256),

rand.Next(256), rand.Next(256));

int x1 = rand.Next(400);

int y1 = rand.Next(400);

int x2 = rand.Next(400);

int y2 = rand.Next(400);

gfx.DrawLine(pen, x1, y1, x2, y2);

}

// Frigör direkt de resurser som användes

pen.Dispose(); gfx.Dispose(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

C#

10.3. VB.NET-versionen

Metoden buttonDraw_Click anropas när användaren klickar på Draw-knappen. Metoden definieras som private eftersom det inte är meningsfullt att anropa den från någon annan klass. De två parametrarna sender och e innehåller information om anropet (se avsnitt 7.2.1 på sid 70). Ingen av dessa behöver användas här.

För att rita i fönstret behövs ett objekt av typen Graphics. Ett sådant skapas på rad 3 genom att metoden CreateGraphics från Form anropas. På rad 4 skapas en penna. Färgen är godtyckligt vald; en färg måste anges men den kommer senare att ändras innan pennan används. På rad 5 skapas en slumptalsgenerator.

Inuti slingan byts pennans färg till en slumpvis vald färg. Metoden Random.Next finns i några olika överlagrade versioner där den som används här tar ett heltal som innebär att det returnerade slumptalet kommer ligga i intervallet [0, 255]. Fyra slumptal som beskriver linjekoordinaterna skapas på raderna 12–15 och används på rad 17 vid uppritningen av linjen som sker genom ett enda anrop till Graphics.DrawLine.

Efter slingans slut anropas Dispose för pennan och Graphics-objektet för att direkt fri- göra de resurser som de använder. (Slumptalsgeneratorn använder inga ohanterade resurser och saknar Dispose-metod.)

10.3

VB.NET-versionen

VB-versionen får ett lite annorlunda utseende:

Private Sub ButtonDraw_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles ButtonDraw.Click

Dim gfx As Graphics = CreateGraphics()

Dim pen As New Pen(Color.Black)

Dim rand As New Random Dim i As Integer

For i = 1 To 500000

pen.Color = Color.FromArgb(rand.Next(256), _ rand.Next(256), rand.Next(256))

Dim x1 As Integer = rand.Next(400)

Dim y1 As Integer = rand.Next(400)

Dim x2 As Integer = rand.Next(400)

Dim y2 As Integer = rand.Next(400)

gfx.DrawLine(pen, x1, y1, x2, y2)

Next

' Frigör direkt de resurser som användes

pen.Dispose() gfx.Dispose() End Sub 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

VB

Denna version är till strukturen mycket lik C#-versionen och den enda egentliga skillnaden finns i metoddeklarationen (raderna 1–2). Nyckelord ByVal anges för att skicka argumen- tet som värde och Handles ButtonDraw.Click visar på VB:s sätt att knyta händelser till metoder (se avsnitt 5.8).

Man ser också hur VB:s syntax medger att klassnamnet vid skapandet av pennan och slumptalsgeneratorn bara behöver anges en gång och att parenteser inte behöver användas för parameterlösa konstruktorer.

10.4

Jämförelse av de olika versionerna

Den meningsfulla jämförelsen här är mellan Visual C++-versionen å ena sidan och C#-/VB- versionerna å den andra. Detta blir också en jämförelse mellan GDI och GDI+. Tydliga skillnader är:

• CClientDC-objektet skapas på stacken med en konstruktor som tar aktuellt fönster som argument medan Graphics-objektet skapas genom att anropa en metod hos fön- sterklassen.

• GDI+ (C# & VB.NET) tillåter att färgen hos en existerande penna ändras medan man med GDI (Visual C++) måste skapa en ny.

• Med GDI+ ritas linjen upp genom att båda ändarna och vilken penna som ska använ- das anges i samma anrop, medan man med GDI med separata anrop väljer penna och startpunkt innan själva linjen ritas.

• .NET-versionerna kräver anrop till Dispose för att deterministiskt frigöra de resurser som grafikobjekten använder medan C++-versionen förlitar sig på objektens destruk- torer.

• .NET har slumptalsgeneratorn Random som är enklare att använda och mer kapabel än C++-funktionen rand (som i exemplet krävde en hjälpmetod).

De praktiska konsekvenserna av dessa skillnader beror av sammanhanget. I kodlängd och subjektiv komplexitet är de olika versionerna (sett till metoden som ritar linjerna, och det är bara den som jämförs) relativt ekvivalenta. Risken att ”göra bort sig” är lite större i C++-versionen i och med att nya pennobjekt måste skapas och att man måste tänka på att frigöra de gamla. (C#- och VB-versionerna skulle drabbas av ett liknande problem om inte möjligheten att återanvända den gamla pennan utnyttjades.) De eventuella skillnaderna i prestanda kommer framgå av avsnitt 11.4.

Kapitel 11

Prestandamätningar

11.1

Testprocedur

I detta avsnitt beskrivs kort hur prestandatesterna har utförts.

11.1.1 Testsystem

Samtliga prestandamätningar har utförts på två olika datorer, benämnda P3 och P4, med följande konfigurationer:

• P3: Celeron 1,3 GHz (256 kB cache, 100 MHz buss), 512 MB 100 MHz SDRAM, grafikkort Matrox MGA-G200 AGP, Windows XP Professional Service Pack 2 • P4: Pentium 4 3,0 GHz (512 kB cache, 800 MHz buss, Hyperthreading), 1 GB DDR-

RAM (PC3200, Dual mode), grafikkort ATI Radeon 9200SE 128 MB, Windows XP Professional Service Pack 2

Mätningarna har utförts utan andra applikationer igång och med ett minimum av prestanda- påverkande bakgrundsprocesser (explorer.exe har avslutats).

11.1.2 Kompilatorer

Följande kompilatorer har använts vid testningen: • VS98: Visual C++ 6.0 Service Pack 5

• VS03: Visual Studio.NET 2003 (.NET Framework 1.1 Service Pack 1) • VS05β: Visual Studio 2005 beta 1 (.NET Framework 2.0 beta 1)

Kompileringarna har gjorts med standardinställningarna i Release-läget. Det är troligt att det hade varit möjligt att förbättra prestandan i en del fall (t ex på den ena maskinen på bekostnad av den andra) genom att ändra inställningarna, men med det stora antalet inställ- ningsmöjligheter hade detta inneburit för mycket jobb. Standardinställningarna ska generera optimerad kod som fungerar bra på alla vanliga processorer. För applikationen WordCount har separata tester (med VS03) även gjorts med standardinställningarna i Debug-läget.

11.1.3 Mätning av exekveringstid

För konsolfönsterprogrammen WordCount och FFT har exekveringstiden mätts med hjälp av det specialskrivna programmet Measure (se [12]). Programmet mäter tiden det tar att exekvera en körbar fil, som medelvärdet av ett valfritt antal körningar. För att få fram exe- kveringstiderna för enbart själva ordräkningen/FFT-beräkningen har den tid det tar att starta processen (och i FFT-fallet att skapa slumpmässig indata) räknats bort genom att exekve- ringstiden även mätts för körbara filer som inte gör något alls respektive enbart beräknar indatan, varefter dessa tider räknats bort.

För att minimera inverkan av hårddiskprestanda och tillfälligheter körs alla programmen en gång omedelbart innan mätningen börjar, och för program med korta exekveringstider (upp till några sekunder) har tiden tagits fram som medelvärdet av 3–100 körningar, något som stöds av mätningsprogrammet.

Tiden för att köra ett program som inte gör någonting alls kan betraktas som en ”startup- tid”. Den skiljer sig åt mellan de olika språken och är därför i sig av visst intresse. Tabell 11.1 listar dessa tider vid kompilering med VS03 respektive J2SE5.0. (Tiderna för VS98 och VS05β, och för VS03 vid kompilering i Debug-läget, avvek väldigt lite och visas där- för inte.) Som synes är ett C++-program som inte gör något alls betydligt snabbare än ett likadant program i de andra språken, men alla tiderna (utom möjligen de för Java) är så korta att de i praktiken troligen inte märks.

Tabell 11.1:Startup-tider (i millisekunder) för program i de olika språken (VS03/J2SE5.0).

Språk

P3

P4

C++ 6 2

C# 78 36

VB.NET 84 40

Java 150 93

För Draw har exekveringstiden mätts manuellt med stoppur från klickning på en knapp i användargränssnittet tills att linjerna slutat ritas. Detta kan förefalla primitivt, men på grund av de långa exekveringstiderna ger det tillräcklig noggrannhet i detta fall.

11.2

WordCount

11.2.1 Indatafiler

Vid testningen av applikationen har tre olika indatafiler av olika storlek använts: • TM. timem11.txt, The Time Machine av H.G. Wells (Project Gutenberg etext).1 • MI. milnd11.txt, The Mysterious Island av Jules Verne (Project Gutenberg etext).2 • KJ. kjv10.txt, The Bible, King James version (Project Gutenberg etext).3

1Sewww.gutenberg.net/etext/35 2Sewww.gutenberg.net/etext/1268 3Sewww.gutenberg.net/etext/10

11.2. WordCount

I tabell 11.2 visas lite statistik för filerna. Det framgår att orden,4inte minst de vanligaste, bara är några få tecken långa. Vid utvecklingen av de olika versionerna användes filen MI. I figur 11.1 visas hur ordfördelningen ser ut i de tre filerna.

Tabell 11.2:Statistisk information om de textfiler som använts som indata till WordCount.

TM

MI

KJ

Antal tecken 200 105 1 150 283 4 445 260

Antal ord 34 863 196 089 854 289

Antal olika ord 5 426 10 742 13 419

Medellängd av alla ord 4,40 4,53 3,91

Medellängd av de olika orden 7,20 7,47 7,07

Medellängd av de 20 vanligaste orden 2,60 2,70 2,85

11.2.2 Exekveringstider

Här presenteras exekveringstiderna för de olika versionerna med respektive indatafil och för de båda testsystemen. Samtliga exekveringstider är exklusive den så kallade startup-tiden (se tabell 11.1). Tabellerna har sorterats efter något författaren döpt till medelindex. Detta värde är uträknat på följande sätt:

• För varje kombination av indatafil och testsystem (totalt sex olika fall) har det geo- metriska5medelvärdet av exekveringstiderna för de olika programversionerna tagits fram.

• Detta medelvärde — vid kompilering med VS03 — har tilldelats index 100 och övriga index har räknats ut baserade på detta.

• Medelindexet är det geometriska medelvärdet av alla indexvärdena för respektive version.

Visual Studio.NET 2003/J2SE5.0

Tabell 11.3 listar resultatet då C++-, C#- och VB.NET-versionerna kompilerats med Visual Studio.NET 2003 och Java-versionerna med J2SE5.0 (de nyaste kommersiellt tillgängli- ga kompilatorerna). Det första man kan lägga märke till är hur enormt mycket det skiljer mellan den snabbaste och den långsammaste versionen. I medeltal (enligt medelindexet) är C++-version 13 över 400 gånger snabbare än C#-version 1! Det motsvarar något i stil med skillnaden mellan den P4-maskin som använts vid testningen och en 20 år gammal 286:a. För den största indatafilen på P3-maskinen skiljer det över 600 gånger.

4Med ord avses här och i fortsättningen teckensekvenser definierade så som framgår av avsnitt 6.2. 5Om det vanliga aritmetiska medelvärdet användes skulle exekveringstider som avvek uppåt få större inver-

kan än sådana som avvek nedåt. Med geometriskt medelvärde fås symmetri i detta avseende. Därmed skulle också samma resultat erhållas om den inverterade exekveringstiden (”snabbheten”) användes istället, något som inte skulle gälla med aritmetiskt medelvärde.

1 2 3 5 10 30 100 300 1 000 3 000 10 000 Antal olika beaktade ord i förekomstordning

10% 20% 30% 40% 50% 60% 70% 80% 90% 100%

Andel av totala antalet ord

TM MI KJ

Figur 11.1:Ordfördelningen i de tre testfilerna. Fördelningen beror som synes relativt lite av tex- tens längd. Det tycks finnas ett approximativt samband som säger att en dubbling av antalet beaktade olika ord ökar andelen av totala antalet ord med ca tio procentenheter. Man kan t ex utläsa att de 20 vanligaste orden svarar för ca en tredjedel av totala antalet ord, de 100 vanligaste för drygt hälften och de 1 000 vanligaste för över 80 %.

Av medelindexet framgår att den totalt sett snabbaste versionen är den som använder möj- ligheten att blanda in assembler i C++-koden. Skillnaden mot de båda rena C++-versionerna 11 och 12 är tydlig om inte överväldigande och varierar också mellan de olika indatafiler- na och mellan maskinerna. Till den snabbaste C#-versionen skiljer det ungefär en faktor 2, vilket är märkbart men ändå placerar denna version i det absoluta toppskiktet.

De C#- och VB-versioner som använder FCL-klassen Hashtable ger inbördes i princip identisk prestanda och placerar sig i mitten, mycket klart slagna av de snabbaste versionerna, men samtidigt före de flesta av de C++-versioner som utnyttjar MFC-klasser. Versionerna som använder map och hash_map (2, 3, 4, 7 och 9) placerar sig före medan de som använder CMap (5, 6, 8 och 10) hamnar efter. På version 9 syns tydligt att det lönar sig att undvika onödiga strängkopieringar; den är ungefär dubbelt så snabb som version 4 som använder string-klassen. Det lönade sig även att implementera en egen hashfunktion; version 4 är i genomsnitt 35 % snabbare än version 3.

De båda Java-versionerna är klart slagna av motsvarande C#-versioner med knappt en faktor två för den optimerade versionen och en faktor tre för den snygga.

11.2. WordCount

Tabell 11.3:Exekveringstider (i millisekunder) med VS03/J2SE5.0.

Version P3 P4

TM MI KJ TM MI KJ

Medel- index

C++ 13 (”Optimerad” med asm) 9 37 140 3 12 43 9

C++ 12 (”Optimerad” v.2) 9 44 170 4 16 61 11

C++ 11 (”Optimerad”) 9 47 180 4 18 79 12

C# 4 (”Optimerad”) 21 68 240 14 31 99 21

C++ 9 (hash_map, const char*) 21 98 330 11 45 150 26

Java 2 (”Optimerad”) 50 170 420 19 63 120 38 C++ 4 (hash_map, string v.2) 43 190 630 23 99 360 54 C++ 3 (hash_map, string) 49 280 1110 24 130 560 73 C++ 2 (map, string) 66 340 1290 35 180 750 96 C++ 7 (hash_map, CString) 80 330 1160 46 200 760 103 C# 2 (Hashtable) 100 520 1680 42 190 640 117 VB.NET (Hashtable) 100 520 1690 42 190 650 117

C++ 10 (CMap, const char*) 82 590 3100 52 380 2010 180 C++ 6 (CMap, CString v.2) 120 760 3790 79 520 2640 244 C++ 5 (CMap, CString) 120 860 5730 83 780 4080 310 Java 1 (HashMap) 400 1260 4260 190 500 1690 354 C++ 8 (CMap, string) 99 2470 19300 60 590 3390 384 C++ 1 (”Simpel”) 390 5760 28800 300 2670 13700 1260 C# 1 (”Simpel”) 1730 21300 85600 950 6510 24900 3740

notera. Ju mindre indatafil, desto mindre skiljer det mellan de olika versionerna. Inte bara de simpla versionerna C++ 1 och C# 1 halkar efter för de större filerna utan även CMap- versionerna. Skillnaden mellan P3- och P4-maskinen varierar mellan endast ca 10 % för versionen C++ 5 på MI-filen till mer än en faktor 5 för C++-version 8 på KJ-filen. C#- och VB-versionerna hör till de vars prestanda ökar mest på den snabbare maskinen medan de C++-versioner som utnyttjar färdiga klasser får en mindre prestandaökning.

Visual C++ 6.0

Visual C++ 6.0 (del av Visual Studio 6.0 från 1998) är visserligen gammalt men används förmodligen fortfarande i ganska hög utsträckning eftersom det kan ha varit svårt att se fördelarna med att investera i de nyare versionerna för enbart programmering i C++. Därför är det intressant att se hur prestandan hos C++-versionerna blir när de kompileras med denna kompilator. De versioner som har tagits med i denna test är de som går att kompilera med Visual C++ 6.0 i det skick som det levereras i, dvs utan att några extra färdiga klasser lagts till. Att så många versioner faller bort beror på att klassen hash_map saknas. I ett par fall har några minimala justeringar fått göras av den del av koden som skriver ut resultatet på skärmen, beroende på gamla regler för variabeldeklaration inuti for-satser och att cout inte samarbetade så bra med CString. Detta är inget som påverkar exekveringstiderna.

Tabell 11.4 listar resultatet. Något överraskande är prestandan för de C++-versioner som använder MFC-klasserna dramatiskt mycket sämre än med de nyare kompilatorerna. Även STL-versionen (C++ 2) blir märkbart om än inte fullt lika dramatiskt sämre. Det har alltså skett en rejäl förbättring av prestandan hos de färdiga klasserna i Visual C++ 7.1 (VS03) jämfört med den äldre versionen. De versioner som använder CMap blir riktigt usla med den

Tabell 11.4:Exekveringstider (i millisekunder) med VS98.

Version P3 P4

TM MI KJ TM MI KJ

Medel- index

C++ 13 (”Optimerad” med asm) 9 39 150 3 12 43 9

C++ 12 (”Optimerad” v.2) 10 43 160 3 15 57 10

C++ 11 (”Optimerad”) 10 47 190 3 16 68 11

C++ 2 (map, string) 120 630 2370 58 330 1300 171

C++ 10 (CMap, const char*) 110 3930 33400 68 1450 13100 688 C++ 6 (CMap, CString v.2) 240 7110 50000 140 2860 18900 1240

C++ 1 (”Simpel”) 400 5760 28900 290 2640 13600 1260

C++ 5 (CMap, CString) 260 7330 48300 150 3050 20500 1300 C++ 8 (CMap, string) 540 11400 68800 240 4870 34800 2150

gamla kompilatorn. Versionerna 5 och 8 får till och med se sig slagna av den extremt simpla version 1! Det här innebär att ett gammalt C++-program som använder färdiga klasser och som skrivits för och kompilerats med Visual C++ 6.0 med stor sannolikhet blir snabbare om det skrivs om i C# eller VB.NET.

Visual Studio 2005 beta 1

För att kunna kompilera den C#-version som använder klassen Dictionary, och för att se om prestandan skiljer sig åt i övrigt har även alla berörda versioner testats med beta 1 av Visual Studio 2005. Det bör naturligtvis beaktas att detta är en betaversion och att siffrorna kan komma att bli annorlunda för den slutliga versionen.

Resultatet listas i tabell 11.5. Exekveringstiderna skiljer sig överlag inte så mycket från de i VS03, men tendensen är att .NET-versionerna och de C++-versioner som använder STL blir märkbart snabbare medan de C++-versioner som använder MFC-klasserna faktiskt blir något långsammare. Noterbart är också att versionerna 11 och 12 märkbart knappar in på version 13; den handskrivna assemblerkoden lönar sig mindre. C#-versionen som använder den nya klassen Dictionary är ca 15 % snabbare än den som använder Hashtable. Då är även den senare något snabbare än med den äldre kompilatorn, och här skiljer det faktiskt lite till VB.NET-versionen. Överlägset störst prestandaförbättring erhåller den simpla C#- versionen. Den är förstås fortfarande dålig, men denna ökning antyder att det för vissa typer av kod skett en rejäl förbättring av C#-kompilatorn och/eller JIT-kompileringen i CLR:en. Visual Studio.NET 2003 med Debug-kompilering

För ett färdigt program görs naturligtvis kompileringen i det optimerade Release-läget, men under utvecklingens gång är det normalt att använda Debug-läget, för att underlätta felsök- ning och eventuellt få kompileringen att utföras snabbare. Det är därför av visst intresse att se hur prestandan blir i detta läge eftersom en kraftig försämring kan vara en olägenhet vid testningen (speciellt för sådana applikationer som utför databehandling i realtid och inte fungerar alls om prestandan faller under en viss nivå).

Tabell 11.6 listar resultatet i Visual Studio.NET 2003. Resultatet visar att medan C#- och VB-versionerna nästan inte påverkas alls blir C++-versionerna märkbart och i flera fall dramatiskt mycket långsammare vid Debug-kompilering. Version 13 är ganska oberörd

Related documents