QString, Performance und Co

Alles rund um die Programmierung mit Qt
Antworten
Tommyknocker
Beiträge: 2
Registriert: 24. August 2007 19:05

QString, Performance und Co

Beitrag 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.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag 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?
Tommyknocker
Beiträge: 2
Registriert: 24. August 2007 19:05

Beitrag 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?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag 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...
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Oder auch einen längeren String verwenden und diesen einige 10000x kopieren...
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag 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
Bitte seid so nett und ändert den Titel von Beiträgen die gelöst wurden, auf [gelöst] Beitragstitel
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag 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??
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
griffin27
Beiträge: 12
Registriert: 13. Februar 2009 15:20

Ich hab heute auch Tests angestellt

Beitrag 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?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag 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.
Antworten