mboost-dp1

Interessant .NET, Mono og Java-test


Gå til bund
Gravatar #1 - Blinklys
7. jul. 2005 13:13

using System.Text;

using System;

namespace TestRegex

{

public class RegexBench2

{

private static String _doc =

"CGAATCTAAAAATAGATTCGGACGTGATGTAGTCGTACAAATGAAAAAGTAAGCC";

private static int ITERATIONS = 1000000;

public static void Main()

{

long start = System.DateTime.Now.Ticks / 10000;

long end;

int length = 1;

for( int i = ITERATIONS; i <= ITERATIONS * 2; i++ )

{

length = (int) (Math.Log((double)i)/Math.Log(4));



String matchthis = generateWord(i, length + 1);

Regex regexpr = new Regex(matchthis, RegexOptions.Compiled);

Boolean b = regexpr.IsMatch(_doc);

if( b )

{

end = System.DateTime.Now.Ticks / 10000;

Console.WriteLine("found {0} at {1} it took {2} miliseconds",

matchthis, i, end - start );

}

}

end = System.DateTime.Now.Ticks / 10000;

Console.WriteLine(".NET regex took {0} miliseconds",end - start);

}

public static String generateWord(int value, int length )

{

StringBuilder buf = new StringBuilder();

int current = value;

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

{

int v = current % 4;

current = current / 4;

buf.Append( convert(v) );

}

return buf.ToString();

}



private static String convert(int value)

{

switch(value)

{

case 0: return "A";

case 1: return "G";

case 2: return "T";

case 3: return "C";

default:

return "0";

}

}

}

}



Hejsa, jeg fandt følgende kode i en Java vs .NET-test (der er også en Java-version). Den matcher en DNA-sekvens op mod en million mulige DNA-strenge De testede Java mod .NET 1.1, og .NET endte med at crashe med en OutOfMemoryException, hvilken den også gjorde på min. Jeg blev dog nysgerrig og gik lidt videre og prøvede også med .NET 2.0 beta 2 og Mono. Resultaterne er rimelig interessante:

.NET 1.1 - finder et matcher, kører længe og crasher til sidst
.NET 2.0 - 31 minutter!
Mono 1.1.8 - 1½ minut!

LOL - ser ud til at Monos implementation er en del bedre på det her punkt end Microsofts egen!
Gravatar #2 - Blinklys
7. jul. 2005 13:15
Java versionen for en god ordens skyld :) tager 9 sekunder på Java 1.5 på den her maskine (P4 3Ghz)


import java.text.*;

import java.util.regex.*;

public class RegexBench2

{

static String _doc = "CGAATCTAAAAATAGATTCGGACGTGATGTAGTCGTACAAATGAAAAAGTAAGCC";

static int ITERATIONS = 1000000;

public static void main(String args[]) {

long start = System.currentTimeMillis();

int length = 1;

for( int i = ITERATIONS; i <= ITERATIONS * 2; i++ ) {

length = (int) (Math.log((double)i)/Math.log(4));

String matchthis = generateWord(i, length + 1);

Pattern regexpr = Pattern.compile(matchthis); Matcher matcher = regexpr.matcher(_doc);

boolean b = matcher.find();

if(b){

long end = System.currentTimeMillis();

System.out.println( MessageFormat.format("found {0} at {1} it took {2} miliseconds",

new Object[] {matchthis, "" + i, "" + (end-start) } )); }

}

long end = System.currentTimeMillis();

System.out.println("Java regex took " + (end - start) + " miliseconds");

}

static String generateWord(int value, int length ) {

StringBuffer buf = new StringBuffer(); int current = value;

for(int i = 0; i < length; i++ ) {

int v = current % 4; current = current / 4; buf.append( convert(v) );

}

return buf.toString();

}

static String convert(int value) {

switch(value) {

case 0: return "A"; case 1: return "G"; case 2: return "T"; case 3: return "C"; default: return "0"; }

}

}
Gravatar #3 - Mort
8. jul. 2005 11:40
Jeg forstår ikke lige hvilken test det er du kører...

Du kører en stump kode på 3 forskellige compilere, men hvad er det lige du tager tid på ?

Så vidt jeg kan læse fra det du har skrevet ser det sådan her ud:
.NET 1.1 - finder et match med det samme.
.NET 2.0 - finder et match efter 31 minutter.
Mono 1.1.8 - finder et match efter 1½ minut.

Hvad er det så der gør at Mono's .NET implementation er den bedste ?
Gravatar #4 - Blinklys
8. jul. 2005 23:59
Sorry forklarede det vidst ikke godt nok - prøver igen :) Det har ikke noget med compilingen at gøre - det er når de kører. Det er et program der matcher en DNA-sekvens op mod en million forskellige DNA-strenge - der er 12 rigtige matches i alt.

.NET 1.1 - er 1 sekund om at finde det første match, derefter kører den (uden at finde flere) og bruger alt hukommelsen og crasher med en OutOfMemoryException.

.NET 2.0 Beta 2 - finder alle 12 matches i løbet af 31 minutter

Mono 1.1.8 - finder alle 12 matches i løbet af ca 1 minut og 30 sekunder.

Java - finder alle 12 matches i løbet ca 9 sekunder.

Det pudsige er at Mono's implementation, af netop denne del af .NET frameworket, ser ud til at være væsentlig bedre end Microsofts egen :)
Gravatar #5 - m_abs
9. jul. 2005 02:10
Link til testen?
Gravatar #6 - mrmorris
9. jul. 2005 05:53
blinklys, for at sammenligne selve VM'erne, kræver det at du selv optimerer din kode. Husk at logaritme funktioner og regulære udtryk er UHYRE tungt at have kørende i loop.

Ved at håndoptimere din kode, kører Java versionen hos mig ca. 8 gange hurtigere og eksekverer på ca. 1½ sekund. Prøv selv at implementere denne optimering i mono og .NET. Jeg er 100% sikker på du vil se meget ens hastigheder.

Tricks jeg har brugt:
- Refaktorér så meget som muligt ud af loops
- Benyt map istedet for switch
- Brug indexOf istedet for regexp til denne simple test
- Hvis du kender størrelsen på en sekvens, brug statisk istedet for dynamisk
- Udnyt at bitvis skift er hurtigere end division/multiplikation

---------------------------------------
import java.text.*;

public class RegexBench
{

static char map[] = {'A','G','T','C'};

static String _doc = "CGAATCTAAAAATAGATTCGGACGTGATGTAGTCGTACAAATGAAAAAGTAAGCC";

static int ITERATIONS = 1000000;

public static void main(String args[])
{
double log4 = Math.log(4);
long start = System.currentTimeMillis();

int length = 1;
String matchthis = null;

for( int i = ITERATIONS; i <= ITERATIONS << 1; i++ )
{
length = (int) (Math.log((double)i)/ log4);
matchthis = generateWord(i, length + 1);

if (_doc.indexOf(matchthis) != -1)
{
long end = System.currentTimeMillis();
System.out.println( MessageFormat.format("found {0} at {1} it took {2} miliseconds",
new Object[] {matchthis, "" + i, "" + (end-start) } ));
}
}

long end = System.currentTimeMillis();

System.out.println("Java regex took " + (end - start) + " miliseconds");
}

static String generateWord(int current, int length )
{
char[] buf = new char[length];

for(int i = 0; i < length; i++ )
{
buf[i] = map[current % 4];
current = current >> 2;
}
return new String(buf);
}
}
Gravatar #7 - Blinklys
9. jul. 2005 10:09
Jep koden er langt fra optimal. Men meningen var nu ikke at lave den hurtigste optimeret kode til den enkelte JVM eller CLR - meningen var at illustrerer hvordan JVM'en og CLR'erne klarer en specifik opgave - nemlig en tung opgave med regular expressions :)
Det kunne bestemt være sjovt at se hvordan dit eksempel kører på de forskellige .NET CLR'er ...

Linket til artiklen er her: Clicky!. Som sagt er det kun .NET 1.1 mod Java (siden er rimelig Java biased, så .NET-fanboys, i er advaret)
Gravatar #8 - Blinklys
9. jul. 2005 11:09
Jeg har lavet en C# version af mrmorris' kode. Denne test giver følgende resultater på min maskine:

Java 1.5 - 828 ms
Mono 1.1.8 - 1390 ms
.NET 1.1 - 4078 ms
.NET 2.0 Beta 2 - 5234 ms

Også rimelig interessant må man sige. Man kunne godt tænke sig at der er en masse debug-enabled kode i betaen af .NET 2.0, så det er bestemt muligt den vll klare sig bedre i final - det vil jo vise sig.


using System.Text;

using System;

namespace TestRegex
{
public class RegexBench3
{

private static char[] map = new char[] {'A','G','T','C'};

private static String _doc =

"CGAATCTAAAAATAGATTCGGACGTGATGTAGTCGTACAAATGAAAAAGTAAGCC";

private static int ITERATIONS = 1000000;


public static void Main()
{

double log4 = Math.Log(4);
long start = System.DateTime.Now.Ticks / 10000;

int length = 1;
String matchthis = null;

for( int i = ITERATIONS; i <= ITERATIONS << 1; i++ )
{

length = (int) (Math.Log((double)i)/log4);
matchthis = generateWord(i, length + 1);

if (_doc.IndexOf(matchthis) != -1)
{

long matchEnd = System.DateTime.Now.Ticks / 10000;
Console.WriteLine("found {0} at {1} it took {2} miliseconds", matchthis, i, matchEnd - start);

}
}

long end = System.DateTime.Now.Ticks / 10000;
Console.WriteLine(".NET regex took {0} miliseconds",end - start);

}

public static String generateWord(int current, int length )
{

char[] buf = new char[length];

for(int i = 0; i < length; i++ )
{
buf[i] = map[current % 4];
current = current >> 2;
}
return new String(buf);

}

}
}
Gravatar #9 - mrmorris
9. jul. 2005 13:50
...meningen var at illustrerer hvordan JVM'en og CLR'erne klarer en specifik opgave - nemlig en tung opgave med regular expressions...

Men et regulært udtryk med blot en streng, vil nogle compilere måske selv optimere anderledes. Altså noget i stil med, brug ikke en motorsav til at skære lister med. Noget CRC/Huffman/Addler/LZW algoritme som virkelig presser compileren fra alle sider, ville nok være det idelle.

Dine resultater følger pænt hinanden. Jeg kunne godt tænke mig lige at sammenligne nogle bytekode/CLR instruktioner men det får jeg først tid til efter weekenden.

Mine erfaringer er ellers, at .NET eksekverer hurtigere end Java men det synes dine resultater af modvise.
Gravatar #10 - Blinklys
9. jul. 2005 14:57
Jeg havde egentlig også forventet, at resultaterne ville ligge meget mere lige i test nummer to. Jeg har også indtryk af at .NET eksekverer hurtigere især i GUI-applikationer. Men det kan selvfølgelig bare have noget at gøre med kompleksitet i WinForms kontra Swing/SWT, og ikke så meget "core"-sproget og den enkelte JVM eller CLR.

Glæder mig meget til at se din test med en eller flere af de algoritmer du nævner - det kan jo sagtens vise sig at det er nogle helt andre resultater. Jeg kunne sagtens forestille mig, at der er andre tests, hvor .NET er hurtigst. Hvilket jo bare vil bevise, at virkeligheden er noget mere nuanceret end ".NET er hurtigst" eller "Java er hurtigst"
Gravatar #11 - DUdsen
9. jul. 2005 19:43
#9 og #10 min opfattelse har altid været at java starter lidt langsommere end .NET men er hurtigere internt end .NET
Det er også billedet af de j2ee vs MS.NET studier jeg har læst, at op til et hvist punkt klare ms.net sig bedre end j2ee men, over en hvis tærskel begynder det at vende i j2ee's favør.
Iøvrigt er WinForms egentligt ikke bare api kald til noget c++ kode menst swing/SWT faktisk kører ingen i JRE'et eller er det bare mig der husker forkert?
Gravatar #12 - Blinklys
10. jul. 2005 08:46
#11

Jeg mener at huske det sådan (ret mig endelig hvis jeg er galt på den):

WinForms bare er en wrapper rundt om det gamle kendte Windows GUI API (skrevet i C eller C++?).

SWT er også en slags wrapper rundt om operativ systemets native GUI. Det er platform-specifikt, og der eksisterer en SWT version til hver platform, f.eks. Windows og GTK+. Koblingen til Java er konsistent gennem de forskellige versioner. Den pågældende version af SWT sørger for at "videreføre" kald til det underliggende operativ systems GUI.

Swing er ren Java
Gravatar #13 - mrmorris
11. jul. 2005 10:53
#12 Det vil forklare mine erfaringer, som primært har at gøre med sløøøve Java GUI'er og ikke rå data-processing. Jeg er dog muligvis noget biased, da jeg er vant til Win32 API'et fra C samt MFC/C++ som, på trods af at det viser sin alder, kører afsindigt hurtigt.

Det er meget logisk hvis WinForms wrapper Win32 API'et, men ikke direkte. Jeg skrev for nyligt noget SDK med identisk .NET og C demo program og der er en verden til forskel mht. reaktionstid for et ganske almindeligt SDI vindue.
Gravatar #14 - KaW
12. jul. 2005 22:52
Jeg får flgn.:
Java regex took 1048 miliseconds
Med den optimerede java og "Java regex took 5624 miliseconds" (Næsten det samme som .NET 2.0 Beta 2) med den første. Bruger en Athlon XP 3200 og java 1.4.2, på Linux.

Ret spændende vil følge med i tråden selvom jeg ikke har så meget at tilføje.
Gravatar #15 - Blinklys
13. jul. 2005 01:59
Interessant at høre nogle resultater fra Linux også :) Hvilken distro er det? Java var rimelig sløj på Linux før i tiden, men efter NPTL er kommet til skulle det være blevet meget bedre.

Jeg kunne også selv godt tænke mig at udføre en test på FreeBSD, især nu efter 5.4 skulle have forbedret performance med tråde. Min server er kun en lille C3-600mhz - næppe nogen Java-kværn :/ så det må vente til jeg får min workstation op at køre.
Gravatar #16 - mrmorris
13. jul. 2005 10:16
Jeg kunne ikke dy mig for at prøve at se hvor hurtig en C version klarer prøven, resultatet er forbavsende tæt på Java (vi taler den optimerede version of koden her). Jeg vil lige kigge lidt mere på det, men hvis det viser sig at holde, tager jeg sku hatten af for Java.
Gravatar #17 - Blinklys
13. jul. 2005 12:10
Interessant. Som vi har været inde på, så tror jeg at Javas ry for at være langsom stammer mest de tunge GUI frameworks. Kan godt huske da jeg i sin tid skulle køre JBuilder 5 på JDK 1.3. Det var bestemt ikke nogen fornøjelse :-S

Der skete dog en stor forbedring af hastigheden i JDK 1.4, og maskinerne er jo også blevet hurtigere siden. I dag synes jeg faktisk både NetBeans (Swing) og Eclipse (SWT) kører ok. Visual Studio .NET virker stadig mere kvikt synes jeg.

Fandt i øvrigt også den her test:
http://www.shudo.net/jit/perf/
Jeg er stødt på den et par gange før, så det kan godt være i også har læst den. Der sammenlignes Java, .NET og en håndfuld C og C++ compilere i en række tests. Nogle af resultaterne er ret interessante.

Men alligevel temmelig imponerende, hvis en C version og Java version ligger så tæt op af hinanden på performance.
Gravatar #18 - KaW
13. jul. 2005 12:58
#15 >
Gentoo linux, og en anden maskine i huset som er 95% identisk med min maskine (Udover at have at Asus Deluxe Motherboard, hvor jeg har et A7V880, altså samme producent) kører Windows og den er en smule langsommere, men det er så lidt at man ikke kan sige at den er bagefter.
Gravatar #19 - Redeeman
27. okt. 2005 15:25
hvis i bruger java på linux, burde i anvende 1.5, da 1.4 er basically ubrugeligt
Gravatar #20 - Blinklys
27. okt. 2005 16:04
#19

Hvorfor er 1.4 ubrugeligt? Jeg har ikke oplevet nogle problemer med det.
Gravatar #21 - mrmorris
27. okt. 2005 16:35
#19 Jeg bruger også 1.4 og har ingen problemer. Det er jo ikke alt Java der er J2SE/Swing eller SUN relateret.
Gravatar #22 - oleo
27. okt. 2005 17:02
#19 Det er at noget vrøvl.
1.4.0 har nogle fejl/uhesigtsmæssigheder, 1.4.2 er god, 1.5 er hurtigere.
Gravatar #23 - Redeeman
28. okt. 2005 00:38
1.5 bruger både væsentligt mindre ram, og er enormt meget hurtigere. - nu ved jeg ikke med ting uden gui, men selv ting som bruger gtk via java er ubrugelige med 1.4 - jeg snakker om azureus, og en go klient - sådan noget som et simpelt go program er langsomt med java 1.4 - og det eneste den skal gære er at tegne en sten når man trykker..

men der er nok mindre forskel på ting som det her, og gui. så det gør måske ikke så meget med data processing som det her.
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login