Seite 1 von 1

QString, Performance und Co

Verfasst: 24. August 2007 20:17
von Tommyknocker
Hallo zusammen,

ich bin neu in QT und auch in diesem Forum also sag mal Hallo all den QT Experten hier im Forum
Kurz zu meiner Person ich hab mich bisher noch nie wirklich mit einem plattform independent Framework auseinander gesetzt, deshalb wollte ich mich etwas weiterentwickeln und bin dabei auf QT 4 gestossen.
Bisher hab ich hauptsächlich ein bisschen in C und JAVA herumexperimentiert und einiges in php/javascript gemacht. Da mir Java aber immer etwas träge vorkam und ich mal was in Richtung Algorithmen machen wollte, nichts schweres einfach mal so aus Spass ein paar Sortieralgos etc. implementieren oder so.

Nun genug der Vorgeschichte und wieder Oon topic, ich hab mir mal QT für Windows (mingw) installiert und hab mir aus der Helloworld eine einfache Testappl. geschrieben und hab mich halt gefragt wie groß der Geschwindigkeitsunterschied zwischen QT und JAVA tatsächlich ist und ich bin leider negativ überrascht worden.
Also ich hab folgenden Code laufen lassen und entsprechendes auch in Java und 'reinem' c++ mit mingw.

Code: Alles auswählen

#include <QApplication>
#include <QPushButton>
#include <QTime>

int main(int argc, char *argv[]) {
    QApplication    app(argc, argv);
    QTime t;
	int i,j,k;
	QString output;

    t.start();

    for(i=0;i<1000;i++) {
      for(j=0;j<1000;j++) {
	  output="Test;";
          for(k=0;k<10;k++) {
            output += k + ";";
          }
       }
    }

    QString text = "Test: " + QString::number(t.elapsed());
    QPushButton     quit(text);
    QObject::connect(&quit, SIGNAL(clicked()), &app, SLOT(quit()));
    quit.show();

    return app.exec();
}
Die Ausführungszeiten liegen bei: (Mittelwert aus 5 Durchläufen)
QT: 20780 ms
Java: 10104 ms
C++: 3456 ms

Wenn ich die Anzahl der Durchlaufe etwas erhöhe und anstelle von String nur int summiere bekomme ich folgendes:
QT: 15812 ms
Java: 6508 ms
C++: 520 ms

Die absoluten Werte sind nicht sehr relevant aber die Verhältnisse sprechen doch eine ziemlich klare Sprache.

Ich kann mir aber eigentlich nicht vorstellen, dass das QT Framework so viel langsamer sein soll als Java. Deshalb wollt ich mal fragen, ob ich vielleicht einen Denkfehler gemacht hab oder woran das liegen könnte.
Bzw. gibt es generell Tipps mit denen man die Geschwindigkeit erhöhen kann?

Danke schon mal für eure Hilfe.

Verfasst: 24. August 2007 20:48
von upsala
Du hast beim summieren von int von C++ zu Qt Unterschiede? Bist du dir schon sicher, daß du die Tests vergleichbar durchgeführt hast?

Verfasst: 24. August 2007 22:00
von Tommyknocker
Ah danke für den Denkanstoß, hab mir das nochmal angesehen und hab mal alles bereinigt und neu kompiliert jetzt passen zumindest die Werte zwischen qt und reinem c++ halbwegs überein also 15722 bzw. 14888.
Interessanterweise liegt der Wert von Java bei der einfachen int Summierung bei 6500, das kann ich zwar nicht verstehen außer wenn mingw im int Bereich im Vergleich zu aktuellen JREs Defizite hat. Denn mit long an Stelle von int ist java mit 18890 wieder langsamer die Werte für c++ und qt bleiben gleich. Aber lassen wir das mal bei Seite.

Gibt es eine Alternative zu QString die etwas performanter ist und gibt es noch weitere Fallstricke in der Hinsicht auf die man aufpassen sollte? Bzw. Objekte die man vermeiden sollte?

Verfasst: 24. August 2007 22:31
von upsala
Kann deine C++-String-Klasse, bzw. Java Unicode? Qt kanns und braucht deswegen mehr Speicher und auch mehr Aufwand zum Konvertieren. Du könntest noch QByteArray testen...

Verfasst: 24. August 2007 22:33
von upsala
Oder auch einen längeren String verwenden und diesen einige 10000x kopieren...

Verfasst: 25. August 2007 10:07
von Volker
Das ganze kann auch stark vom Compiler abhängen. Ich hab selbst mal ein Performance Test gemacht um eine kleine Matrix Bibliothek und die Auswirkungen von SSE Befehlen zu testen. Bei ein paar Millionen Matrix Operationen hatte ich im Release Modus unter VC++ 2005 zunächst ca. 3 Sekunden Laufzeit. Als ich die Profilgesteuerte Optimierung von VC2005 verwendet hab, ließ sich das ganze auf 0.18 Sekunden optimieren. Allerdings ist das ein Extrembeispiel, da das Programm nur aus den Matrixoperationen und sonst nichts bestand. In alltäglichen Anwendungen dürfte der Effekt nicht so groß sein, da die Komplexität viel größer ist und der Compiler nicht so gut optimiert. Tortzdem hängt vieles am Compiler. Gerade z.B. die STL Klassen sind unter VC2005 im Debug Modus deutlich langsamer als unter 2003, im Release Modus dagegen entweder genauso schnell oder sogar schneller.
Da es bei Java soweit ich weiß keinen Debug oder Release Modus gibt, dürfte der Compiler stehts versuchen optimalen Code zu verarbeiten. Glaube auch gehört zu haben, dass die Compiler für virtuelle Machinen Code besser optimieren können. Allerdings kommt dabei immer noch der Overhead für die Virtuelle Machine und die Garbage Collection dazu

Verfasst: 27. August 2007 10:22
von Christian81
Nicht nur vom Ccompiler - sondern auch vom Debug/Release Modus. Und ein wenig optimieren und Qt helfen kann man auch noch...

Code: Alles auswählen

output = QLatin1String("Test");

output += k + QLatin1String(";");
oder noch besser
output += k + ';';

übrigens: Wolltest du k wirklich so verwenden??

Ich hab heute auch Tests angestellt

Verfasst: 22. Juni 2010 21:43
von griffin27
Hallo,

ich möchte den Thread wieder aufwärmen.

Weil wir auf der Uni nur Java lernen, ich aber mit C aufgewachsen bin und dann einmal über Qt gestolpert bin (zum Glück), wollte ich heute einmal einen Performance-Vergleich eines Algorithmus in Java und in Qt anstellen.

Es geht um eine selbst-geschriebene String-Suche in einem langen Text (145kB). Der Algo selbst ist nicht optimiert.

Dabei ist Qt ca. gleich-schnell/-langsam wie Java. Das hab ich mir echt nicht erwartet. Ich hab mit MinGW auf WinXP kompiliert. Wichtig ist natürlich eine Release-Version zu erstellen. Die Debug-Version ist um ca. das 10-fache langsamer...

Hier ein Ausschnitt des verwendeten Codes:

Code: Alles auswählen

// returns the number of occurrences of pat in text
int BruteForceSearch::searchWW(const QString& text, const QString& pat) {
	int num = 0;
	int n = 0, m = 0;

	while (n < text.length()) {
		if (text.at(n) == pat.at(0)) {
			m = 1;
			while (m < pat.length() && n + m < text.length() && text.at(n + m)
					== pat.at(m)) {
				m++;
			}
			if (m == pat.length() && (m + n + 1 == text.length() || (m + n + 1
					< text.length() && !text.at(m + n).isLetter())))
				num++;
			else
				n += m;
		}
		// skip word in text
		while (n < text.length() && text.at(n).isLetter())
			n++;
		while (n < text.length() && !text.at(n).isLetter())
			n++;
	}
	return num;
}
Die Strings wurden vor der Zeitmessung eingelesen, und es sollte nirgends eine tiefe Kopie geben.
Die Funktion wurde für verschiedene Worte je 1000-mal aufgerufen; dies dauert immer ca. 3s. In Java ebenfalls.

Angeblich ist Qt ja in der Reaktionszeit bei GUI-Anwendungen hervorragend, in Sachen Algorithmen ist Qt mit Java vergleichbar. Letzteres bestätigt sich durch meine Messungen.

Wenn auf der Uni im Zusammenhang mit Java von Performance gesprochen wurde, Scherzte ich oft darüber Java überhaupt mit Performance in Verbindung zu bringen :-)
Da hab ich leider weit gefehlt.

lg, Karl

EDIT: hab mir heute gedacht, dass man eine Bedingung mit vielen UNDs mit deMorgan auf eine Bedingung mit vielen ODERs umformen kann, wenn es recht wahrscheinlich ist, dass sie zutrifft. denn trifft ein ODER-Statement zu, trifft gleich die ganze Bedingung zur (bzw. halt nicht durch die Invertierung über alles).
Der Compiler kann soetwas nicht übernehmen, oder? Der weiß ja nicht, was wahrscheinlicher ist...
Ich hab mir das noch nicht fertig durchgedacht, aber kann man damit prinzipiell auch optimieren?

Verfasst: 22. Juni 2010 22:02
von upsala
Hier wurden keine aufwendigen Algorithmen benutzt, sondern nur einfache Indexzugriffe. Da läst sich nicht viel optimieren.

Der JIT-Compiler von Java wird wahrscheinlich einen ähnlichen Maschinencode erzeugen, somit kann sich kein großartiger Geschwindigkeitsunterschied ergeben.