C# C# Performance langsam

F

FredyH

Gast
Hallo,
Ich hab mir mal zum spaß ein Brute-Force Programm geschrieben, um zu testen wie lang meine passwörter standhalten. Dieses Programm habe ich in C#, Java und C++ geschrieben um die Performance der Sprachen zu vergleichen.
Bei C++ bekomme ich 10 Millionen versuche die Sekunde (in der Konsole)
Bei Java 1,5 Millionen(vorallem wegen GUI)
und in C# nichtmal 1000.
Ich weiß wirklich nicht woran das liegt, ich benutze die gleiche Logik für alle 3 Sprachen (je nach Sprache leicht abgeändert) und ich dachte eigentlich sogar, dass C# eine bessere Performace hat als Java.
Code in Java:
Code:
static long last;
static JFrame f;
static JButton b;
static JTextField feld;
static JLabel l;
static JLabel iter;
static JLabel iterps;
static String inputstring = "";
static int curtime;
static String curstring = " ";
static char curchar;
static int charint = 0;
static int maxpos = 0;
static int count = 0;
static volatile RunThread t;
public void run()
		{
			last = System.nanoTime() / 1000000;
			while (!curstring.equals(inputstring))
			{
				charint++;
				count++;
				curchar = (char) charint;
				if (count % 1000 == 0)
				{
					iter.setText("Iterations:" + count);
					iterps.setText("Iterations/s: "
							+ ((float) count / ((float) curtime / 1000)));
					l.setText("Time: " + ((float) curtime / 1000));
				}
				long newlast = System.nanoTime() / 1000000;
				long dif = newlast - last;
				curtime += dif;
				last = newlast;
				char[] chararray = curstring.toCharArray();
				if (charint >= 255)
				{
					charint = 0;
					int bufpos = 0;
					while (bufpos < chararray.length)
					{
						for (int i = 0; i < bufpos; i++)
						{
							chararray[bufpos] = (char) 0;
						}
						if (bufpos == maxpos)
						{
							maxpos++;
							char[] buffer = new char[chararray.length + 1];
							for (int i = 0; i < buffer.length; i++)
							{
								buffer[i] = (char) 0;
							}
							chararray = buffer;
						}
						if (chararray.length > bufpos + 1)
						{
							int x = (int) chararray[bufpos + 1];
							x++;
							chararray[bufpos + 1] = (char) x;
							if (!(x > 255))
								break;
						}
						bufpos++;
					}
				}
				chararray[0] = curchar;
				curstring = String.valueOf(chararray);
				feld.setText(curstring);
				if (t == null)
					break;
			}
			iter.setText("Iterations:" + count);
			iterps.setText("Iterations/s: "
					+ ((float) count / ((float) curtime / 1000)));
			l.setText("Time: " + ((float) curtime / 1000));
			feld.setText(curstring);
			b.setText("Start");
			feld.setFocusable(true);
			t = null;
			t2 = null;
		}

Code in C#:
Code:
String inputstring = "";
long curtime;
String curstring = " ";
char curchar;
Thread t;
int charint = 0;
int maxpos = 0;
int count = 0;
static long last;

 public void run()
        {
            last = Environment.TickCount / 1000;
            while (!curstring.Equals(inputstring))
            {
                charint++;
                count++;
                curchar = (char)charint;
                if (count % 10000 == 0)
                {
                    SetText("Iterations:" + count, label2);
                    SetText("Iterations/s: " + ((float)count / ((float)curtime)), label3); ;
                    SetText("Time: " + ((float)curtime), label1);
                }
                long newlast = Environment.TickCount / 1000; ;
                long dif = newlast - last;
                curtime += dif;
                last = newlast;
                char[] chararray = curstring.ToCharArray();
                if (charint >= 255)
                {
                    charint = 0;
                    int bufpos = 0;
                    while (bufpos < chararray.Length)
                    {
                        for (int i = 0; i < bufpos; i++)
                        {
                            chararray[bufpos] = (char)0;
                        }
                        if (bufpos == maxpos)
                        {
                            maxpos++;
                            char[] buffer = new char[chararray.Length + 1];
                            for (int i = 0; i < buffer.Length; i++)
                            {
                                buffer[i] = (char)0;
                            }
                            chararray = buffer;
                        }
                        if (chararray.Length > bufpos + 1)
                        {
                            int x = (int)chararray[bufpos + 1];
                            x++;
                            chararray[bufpos + 1] = (char)x;
                            if (!(x > 255))
                                break;
                        }
                        bufpos++;
                    }
                }
                chararray[0] = curchar;
                curstring = new string(chararray);
                SetText(curstring, textBox1);
                if (t == null)
                    break;
            }
            SetText("Start", button1);
            t = null;
        }

Es ist unschön zu lesen und im prinzip nur von Java kopiert(deswegen die namen merkwürdig) aber im Prinzip sollte es keinen großen unterschied geben...
Beide Methoden laufen in einem Thread.
Nun meine Frage:
Woran liegt es, dass C# so langsam ist, und wie kann ich es verbessern, dass es zumindest genau so gut ist wie Java?

soul0ry
 
Zuletzt bearbeitet von einem Moderator:
??? Du stellst Code für einen BruteForce-Angriff ins Internet ??? Keine Ahnung ob der funktioniert. Ich wills auch gar nicht wissen. Deine nächste Frage wird dann sein: "Ich hab zum Spaß einen Virus geschrieben, ist der Code korrekt ?"
 
@Wunderkind
Natürlich nicht...
1. Funktionert der code und ich will nicht wissen warum er nicht funktioniert
2. Ist Brute-Force eine Methode zum herausfinden von passwörtern(extrem ineffizient, nur für maximal 4 stellige passwörter gut sonst dauert es mehrere Jahre)
3. Kann man damit nur in eine Textbox sein passwort eingeben und es versucht es dann herauszufinden...
4. Wollte ich nur zum spaß so ein Programm schreiben und um rauszufinden wieso C# langsamer ist...
5. Ist es nicht illegal
 
Wunderkind schrieb:
??? Du stellst Code für einen BruteForce-Angriff ins Internet ??? Keine Ahnung ob der funktioniert. Ich wills auch gar nicht wissen. Deine nächste Frage wird dann sein: "Ich hab zum Spaß einen Virus geschrieben, ist der Code korrekt ?"

Du bist auch ein wenig zurückgeblieben oder? Lass die Finger von der Tastatur wenn du außer Humbug nichts anderes beizutragen hast.


Welcher Compiler/ Version?
 
Du stellst Code für einen BruteForce-Angriff ins Internet ???
Meine Güte ... :rolleyes:
Er testet übrigens nur ganz primitiv in einer Schleife ob der generierte String auf einen eingebenen Text passt, da ist wohl garnichts dran.

@Thread: Da das für Java kein ausführes Stückchen Code war hab ich das GUI-Zeug rausgenommen, stattdessen in der Konsole ausgeben lassen und gestartet. Ich komme auf ~22 Millionen Iterations/s
Zu den Performanceunterschieden kann ich nichts sagen. Aber so schlecht kann C# garnicht sein, da muss irgendwo ein Fehler sein.
 
Du könntest mal mit einem Profiler den Programmablauf analysieren, vielleicht findest du was brauchbares. Könnte mir höchsten vorstellen, dass du eine Datenstruktur ineffizient genutzt hast oder ständig Objekte allokiert und wieder gelöscht werden.
 
Ich kenn mich jetzt nicht so in c# aus, aber:
char[] buffer = new char[chararray.Length + 1]; und curstring = new string(chararray);

dort müsste in jeder Iteration der Speicherplatz für das gesamte Array reserviert werden, das ist sehr schlecht für die Performance

Und wenn du weißt das dein Passwort maximal n Zeichen lang ist, dann ist es besser das Array statisch zu definieren.
 
@Marco01_809:
Hab nur die relevanten infos rauskopiert, wäre sonst zu lang.

@Turas:
Werde ich gleich mal machen

@dude90:
Ich weiß nicht, das erklärt kaum, wieso java 1000 mal schneller ist...

@Blade28213
Eingebauter Compiler von Visual Studio 2010

Danke aufjedenfall für die Beiträge bis jetzt :)
 
Wenn du dynamisch in der Laufzeit mehrere Strings/allg. Datentypen ohne definierte Anzahl in C# anlegen willst, würde ich eher zu Listen als zu Arrays raten, da Arrays sehr viel Speicherplatz und CPU-Leistung fressen.

In Java sind Arrays dagegen meines Wissens nach viel performanter als in C#.

Daran könnte der Leistungsunterschied liegen.
 
@Blade28213
Also ich muss doch sehr bitten. Das ist nun wirklich kein Umgangston.

@soul0ry
OK. Hab den Text nicht richtig gelesen. Den Code allerdings auch nicht. Meine Schuld. Wollte dir ja auch nichts unterstellen. Ich vermutete lediglich eine unüberlegte Aktion deinerseits, was in einer unüberlegten Aktion meinerseits endete.
 
Performance-Tests mit I/O kann man vergessen. Ich habe eben das <edit>C#-</edit> Programm laufen lassen (alles in die Konsole eben, nur die ausgabe des aktuellen Strings in jeder Iteration hab ich weggelassen). Damit komm ich auf fast 8 Millionen Iterationen pro Sekunde laut Deiner Ausgabe. Meine Kiste ist mittlerweile 4 Jahre alt (ein alter Athlon), also alles andere als neu :-)

Im übrigen lohnt sich das "Variablen-wiederverwenden", wie Du das hier im C-Style machst, in Hochsprachen wie Java und C# (in C++ schon!) überhaupt nicht. Hier sollte man die GC seine Arbeit machen lassen; durch künstliches Optimieren und C-Style-Programmieren lässt man diese Sprachen auch schlechter da stehen als sie sind (hier ist einfach "gut gemeint" oftmals != gut^^). Ich hab aber zugegebenermaßen nicht genauer reingeschaut, ist nur so ne Anmerkung.
 
Zuletzt bearbeitet:
Da ich an bestimmten Indizes den Wert ändern möchte ist wahrscheinlich ein Array die bessere Lösung, denn die Methode einer Liste, um den Wert an einem bestimmten Index zu ändern kostet auch Leistung.
Und es wäre schon sehr schlecht von C# wenn das dazu führt, dass es 1000 mal langsamer läuft...

@captmcneil:
Das java oder das C# programm?

@Wunderkind:
Passiert ;)
 
Zuletzt bearbeitet von einem Moderator:
Heißt das also, dass die GUI in C# soviel Performance frisst?
Kannst du bei dir bitte mal das programm mit GUI testen?(im Anhang)
 

Anhänge

  • BruteForce.rar
    4,7 KB · Aufrufe: 162
soul0ry schrieb:
Heißt das also, dass die GUI in C# soviel Performance frisst?
Kannst du bei dir bitte mal das programm mit GUI testen?(im Anhang)
Dein Programm mit GUI sagt 5000 Iterations per second.

Aus meiner Erfahrung her kann das locker sein. Je nachdem, wie Du die GUI ansteuerst, kann man da ziemliche katastrophen veranstalten - ich vermute, Du aktualisierst jedesmal das Label in jeder Iteration. In EventDispatched-Thread von Swing mag das weniger, in WinForms oder WPF mehr ausmachen, aber der Punkt ist, eine GUI aktualisiert man nicht synchron zum Algorithmus. Das was Du dann testest, ist nämlich nicht mehr dein Algorithmus, sondern die GUI - und die C#-GUI-Bibliotheken machen an der Stelle einfach eine ganze Menge mehr und anders als Swing.

Wenn Du objektiv vergleichen willst, würde ich für den Anfang mal in fest definierten Zeitintervallen (alle 100 ms oder so) die GUI per Event aus dem Algorithmus heraus aktualisieren.
 
Zuletzt bearbeitet:
Öhm Leute, es geht hier um den Vergleich. Da muss man schon beide Tests ausführen.
 
Ich update die Labels alle 10000 ticks, mit einer Invoke methode(thread safe), das sollte also kaum allzuviel performance kosten.
Gibt es denn einen Weg diese Sachen die Windows Forms mehr machen für die Performance zu deaktivieren?
 
captmcneil schrieb:
Im übrigen lohnt sich das "Variablen-wiederverwenden", wie Du das hier im C-Style machst, in Hochsprachen wie Java und C# (in C++ schon!) überhaupt nicht.

Und auch da nur, wenn die Variable von einem Typ ist, für den construction und destruction teuer sind. Mit built-in Typen wie int, float, etc. und kleinen Objekten, die zwecks Initialisierung / Zerstörung keine aufwändigen Dinge wie z.B. new / delete aufrufen, bist du auch in C++ besser beraten, von Variablenwiederverwendung abzusehen und stattdessen die Variable in den kleinstmöglichen Gültigkeitsbereich zu verschieben.
 
@antred:
Die globalen variablen werden nie neu erstellt, sondern müssen immer da bleiben (außer der string/chararray, da die sich ändern), bei den lokalen variablen benutze ich keine neu.
Ergänzung ()

Ok captmcneil hatte recht, zwar habe ich die labels nur alle 10000 ticks aktualisiert, das Textfeld aber jeden tick...
jetzt habe ich 30 millionen ticks die sekunde.
Und ich denke die Methode die labels alle 100ms zu aktualisieren ist auch besser und werde ich implementieren.
Danke aufjedenfall für die schnelle und gute hilfe :)
 
Zuletzt bearbeitet von einem Moderator:
soul0ry schrieb:
Ich update die Labels alle 10000 ticks, mit einer Invoke methode(thread safe), das sollte also kaum allzuviel performance kosten.
Gibt es denn einen Weg diese Sachen die Windows Forms mehr machen für die Performance zu deaktivieren?

Du gibst die Counter alle 10000 Ticks aus, aber nicht die Ausgabe des aktuellen Strings. Die killt Dich hier! (Zeile 67 in deinem C#-Listing)

Probier's mal mit irgendwie sowas:

PHP:
new Thread(() =>
            {
                while (true)
                {
                    Console.WriteLine(curstring); // TODO: Ausgabe
                    Thread.Sleep(100);
                }
            }).Start();

Ist hacky, ich weiß... diese Implementierung gibt alle 100ms auf der Konsole den aktuellen String aus. Wenn Du nicht auf die Konsole schreibst, sondern WinForms ansteuerst, kanns sein, dass er sich beschwert, weil es nicht erlaubt ist, ein UI-Element in einem anderen Thread zu manipulieren. Dann musst in Deiner Hauptklasse ein Event registrieren, und in dem o.g. Thread das Event auslösen.
 
Zuletzt bearbeitet:
Zurück
Oben