inline
-
Hallo zusammen,
gibts in Java sowas wie inline bei C++? Also um den Methodenrumpf an die rufende Stelle reinzukopieren...
Gruß, in
-
Das machen heutige JVMs automatisch zur Laufzeit, falls es sich lohnt. Da muss man nicht extra bekanntgeben, dass die das machen dürfen.
-
Da dachte ich, ich könnt mal noch was optimieren, aber ist schon optimiert ;).
So ein Mist, irgendwie ist das alles voll langsam, was ich mir hier zusammengecodet hab. Ich mach ne Datenbankabfrage (werden ~ 1000 selects abgesetzt) und bau das dann in ne xml struktur auf. es ist so langsam!
vorher hatte ich noch ne hashmap eingesetzt, um die elemente aus der datenbank zu verwalten, das hat aber auch viel zu viel zeit gekostet (gibts da was flotteres?). zur zeit nehm ich n string array, aber das is halt so unkomfortabel.
und beim zusammensetzen der xmlstruktur geht natürlich am meisten zeit flöten. ich nehm schon größtenteils stringbuffer. langsam ist das immer noch (vielleicht schneller als mit strings, aber...).
ich raff das irgendwie nicht, ich baue eine anwendung nach, die ich in php geschrieben hatte. da is das in null komma nix fertig. und java kann ich quasi zugucken, wie die seite aufbaut.
gibts nicht noch ein paar gute performance tricks für solche Sachen? Kann eventuell n anderer mysql treiber schon was bringen (indizes und so hab ich auf der db schon angelegt)? oder irgendwas? ich profile schon wie ein wilder, aber es ist eben alles langsam, und das problem ist halt, dass nicht meine methoden die langsamen sind, sondern die, die ich von irgendwelchen standardsachen verwende ;).
-
...zu viele Smileys. ...zeig mal Code! :p
-
also ich schnippel mal was zusammen.
so connecte ich zur db:
Context ctx = new InitialContext(); Context envCtx = (Context)ctx.lookup("java:comp/env"); DataSource ds = (DataSource)envCtx.lookup("jdbc/"+db); conn=ds.getConnection();
abfrage:
res = stat.executeQuery(sql);
rückgabe der ergebnisse (vorher hatte ich hier ne hashmap mit allen feldern erzeugt und die zurückgegeben) - die methode is schonmal ziemlich langsam:
String erg; try { erg=res.getString(spalte); } catch (SQLException e) { erg=null; } return erg;
und der xml kram is der absolute killer, ich hab eigentlich schon entschieden, das einfach wegzulassen und eben nicht mit xml/xslt zu arbeiten, weil es einfach zu langsam ist (nicht die transformation, die erzeugung von xml):
StringBuffer erg=new StringBuffer(); erg.append("<rechnung>"); erg.append("<rechnungsnummer>"+getRechnungsnummer()+"</rechnungsnummer>"); erg.append("<datum>"+member[mDatum]+"</datum>"); erg.append("<kundennummer>"+member[mKundennummer]+"</kundennummer>"); erg.append("<kundenname>"+StringEscapeUtils.escapeXml(member[mKundenname])+"</kundenname>"); erg.append("<vertragsnummer>"+member[mVertragsnummer]+"</vertragsnummer>"); erg.append("<gesamtnetto>"+gesamtsumme+"</gesamtnetto>"); erg.append("<gesamtbrutto>"+gesamtsummeMitMwst+"</gesamtbrutto>"); for(int i=0;i<anzPosten;i++) { erg.append(posten[i].toXml()); } erg.append("</rechnung>"); return erg.toString();
da verwende ich schon mein stringarray. als ich noch die hashmap hatte, war die ganze geschichte natürlich erheblich einfacher erweiterbar, aber was nützt es, wenn der nicht fertig wird :).
-
ach mist, hab noch was vergessen:
[...]
was, nur 10 smilies erlaubt? was is denn das.. na dann:
-
in schrieb:
erg.append("<rechnungsnummer>"+getRechnungsnummer()+"</rechnungsnummer>");
Ist jetzt aber nicht der Sinn von nem Stringbuffer dort wieder Strings zu "addieren".
Mach doch so:erg.append("<rechnungsnummer>"); erg.append(getRechnungsnummer()); ...
-
Und wo ist da jetzt genau der Flaschenhals? Hast Du mal gemessen?
Ich kann dazu leider nur wenig sagen. Kenne mich mit solchen Datenbanksachen nicht aus. Zum StringBuffer kann ich dir aber schon 2 Tipps geben:
1. Nutze StringBuilder statt StringBuffer, wenn Du kannst.
2. Wenn Du die benötigte Größe des StringBuffers oder StringBuilders vorher kennst oder abschätzen kannst, dann erzeuge Dir gleich durch einen passenden Konstruktoraufruf einen StringBuffer oder StringBuilder, der groß genug ist.
-
für XML verwende ich immer JDOM http://www.jdom.org/.
Ich weis nicht ob das schneller als StringBuffer ist. Wenn es nicht Thread-Saved sein muss kannst du StringBuilder nehmen. Ist das gleiche wie StringBuffer nur halt nicht Thread-Save, aber schneller.vorher hatte ich noch ne hashmap eingesetzt, um die elemente aus der datenbank zu verwalten, das hat aber auch viel zu viel zeit gekostet (gibts da was flotteres?). zur zeit nehm ich n string array, aber das is halt so unkomfortabel.
Wenn du gezielt Elemente ansprechen willst, ist eine HashMap ziemlich flott. Also wenn du Name = Element hast, dann ist der Zugriff auf das Element über den Name bei einer HashMap schnell.
-
@in: Hallo??! Du machst Datenbank-Zugriffe und XML processing und sch... wegen inlining rum? Da fehlt es schon sehr viel weiter, als das irgendeine Funktion nicht geinlined wird. Mach dich mal mit der Benutzung eines Profilers vertraut und versuche, genauestens herauszufinden, was viel Zeit kostet. Die Methoden der Standard-Bibliothek sind in der Regel nicht so langsam implementiert, aber man muss sie korrekt benutzen.
Es kann dir auch keiner sagen, ob eine Hashmap jetzt besser oder schlechter ist, wenn du nicht sagst, wofür du sie verwenden willst.
-
Und wo ist da jetzt genau der Flaschenhals? Hast Du mal gemessen?
Java selber ist der Flaschenhals
Java sollte man immer nur als letzten Ausweg nehmen.
Aber im richtigen Forum bist du ja immerhin schon.
-
Ist jetzt aber nicht der Sinn von nem Stringbuffer dort wieder Strings zu "addieren".
stimmt, aber das problem liegt ja im StringBuffer ;). Das ist halt immer noch so langsam. Die meiste Zeit geht in der Klasse StringBuffer drauf. Halt im Konstruktor, in der append Methode (am allermeisten) und in der tostring methode.
Und wo ist da jetzt genau der Flaschenhals? Hast Du mal gemessen?
jip, wie gesagt, meine toxml methode braucht am meisten zeit (also auch die methode selber, nicht nur der stringbuffer).
1. Nutze StringBuilder statt StringBuffer, wenn Du kannst.
kann ich leider nicht, nutze java 1.4 , da scheints den noch nicht zu geben :(.
2. Wenn Du die benötigte Größe des StringBuffers oder StringBuilders vorher kennst oder abschätzen kannst, dann erzeuge Dir gleich durch einen passenden Konstruktoraufruf einen StringBuffer oder StringBuilder, der groß genug ist.
okay, das hilft etwas, die expand methode hat auch einiges an zeit verbraten.
für XML verwende ich immer JDOM http://www.jdom.org/.
ist eher zum parsen von bäumen, ich erstelle ja xml.
Wenn du gezielt Elemente ansprechen willst, ist eine HashMap ziemlich flott. Also wenn du Name = Element hast, dann ist der Zugriff auf das Element über den Name bei einer HashMap schnell.
naja, das war schon genau das was ich wollte (hab die spalten der tabelle als key verwendet, und die werte halt als attribute, aber die vielen zugriff waren zu langsam).
so, vorneweg jetzt erstmal danke für eure tipps, es wäre echt toll, wenn ich die geschichte noch etwas schneller kriegen könnte ;).
@in: Hallo??! Du machst Datenbank-Zugriffe und XML processing und sch... wegen inlining rum? Da fehlt es schon sehr viel weiter, als das irgendeine Funktion nicht geinlined wird. Mach dich mal mit der Benutzung eines Profilers vertraut und versuche, genauestens herauszufinden, was viel Zeit kostet. Die Methoden der Standard-Bibliothek sind in der Regel nicht so langsam implementiert, aber man muss sie korrekt benutzen.
Es kann dir auch keiner sagen, ob eine Hashmap jetzt besser oder schlechter ist, wenn du nicht sagst, wofür du sie verwenden willst.
das hilft mir wirklich weiter. ich bin nicht der super java crack, aber deine aussagen lassen auch keine besonderen kenntnisse spüren. ich hab geschrieben, das beim zusammenbau der xml struktur die meiste zeit flöten geht. dass das so sein würde, konnte ich auch schon vor der implementierung abschätzen. natürlich habe ich nachgemessen, wer genau wie schuldig ist. und hättest du meine posts richtig gelesen, hättest du das auch gemerkt. und das sind nunmal die methoden von java.lang. vielleicht benutze ich die nicht richtig, ich will mal im augenblick noch davon ausgehen, deswegen schreibe ich ja überhaupt hier. wenn es nicht an meiner fehlerhaften benutzung liegen würde, hätte c++ler wohl recht mit:
Java selber ist der Flaschenhals
und falls du noch n beispiel haben willst, wie ich mit einer hashmap elemente einer db verwalten möchte (wenn ich dafür von dir einen _nützlichen_ tipp erhalte), bittesehr:
public HashMap next() throws SQLException{ HashMap erg=new HashMap(); if (!res.next()) return false; int anz=resmeta.getColumnCount(); for( int i=1; i<=anz; i++ ){ erg.put(resmeta.getColumnName(i),res.getString(i)); } return true; }
so hatte ich mir ne connect klasse geschrieben, mit der ich recht angenehm und wiederverwendbar datenbankverwaltung ermögliche. aber das war halt grottenlangsam.
viele grüße,
in
-
c++ler schrieb:
Und wo ist da jetzt genau der Flaschenhals? Hast Du mal gemessen?
Java selber ist der Flaschenhals
Java sollte man immer nur als letzten Ausweg nehmen.
Aber im richtigen Forum bist du ja immerhin schon.Ach, Java ist inzwischen eigentlich schon ganz flott. ...und wird immer besser und schneller. Da kann man sich eigelich nicht beschweren, wenn man die Entwicklung der letzten Jahre betrachtet. Aber man muss halt, wie in jeder Sprache, wissen, wo die Schwachstellen in der Sprache oder der Standardbibliothek liegen, die man bei der Programmierung beachten sollte.
-
in schrieb:
nutze java 1.4 , da scheints den noch nicht zu geben :(.
Bist Du an Java 1.4 gebunden? Wenn nein, empfehle ich Dir in jedem Fall, auf eine aktuelle Javaversion umzusteigen. mit neueren Versionen kommen ja auch immer Verbesserung bezüglich der Performance der Standardbibliothek und der JVM im Allgemeinen. Wer weiß: Vielleicht beseitigt das alleine schon deinen Flaschenhals. ...ausprobieren macht klug.
-
Gregor schrieb:
c++ler schrieb:
Und wo ist da jetzt genau der Flaschenhals? Hast Du mal gemessen?
Java selber ist der Flaschenhals
Java sollte man immer nur als letzten Ausweg nehmen.
Aber im richtigen Forum bist du ja immerhin schon.Ach, Java ist inzwischen eigentlich schon ganz flott. ...und wird immer besser und schneller. Da kann man sich eigelich nicht beschweren, wenn man die Entwicklung der letzten Jahre betrachtet. Aber man muss halt, wie in jeder Sprache, wissen, wo die Schwachstellen in der Sprache oder der Standardbibliothek liegen, die man bei der Programmierung beachten sollte.
Aber sind String (oder Array) -Operationen nicht gerade eine Schwachstelle von Java? Die String Klasse ist doch total lahmer Müll. Und wenn man den StringBuffer mit den einfachen C Char Array (strcat...) vergleicht ist er wahrscheinlich auch deutlich langsamer. Und die ständigen ArrayIndexOutOfBound überprüfungen machen das ganze ja auch nicht gerade schnell.
-
rdgdfsgdf schrieb:
Aber sind String (oder Array) -Operationen nicht gerade eine Schwachstelle von Java? Die String Klasse ist doch total lahmer Müll. Und wenn man den StringBuffer mit den einfachen C Char Array (strcat...) vergleicht ist er wahrscheinlich auch deutlich langsamer. Und die ständigen ArrayIndexOutOfBound überprüfungen machen das ganze ja auch nicht gerade schnell.
Das ist eher kein Performanceproblem von Java. Die String-Klasse hat ihre Stärken und Schwächen. Um die Schwächen auszugleichen, gibt es StringBuffer oder auch StringBuilder. Wenn man mit Java programmiert, sollte man eigentlich recht schnell lernen, wo man das eine und wo man das andere einsetzt. Die String-Klasse ist halt immutable und nicht wie eine dynamische Datenstruktur aufgebaut. Das sollte man wissen.
Die Bereichsprüfungen bei Arrays sind auch kein echtes Performanceproblem. Du kannst ja mal ein C++ Programm und ein Java Programm vergleichen, die beide sehr viele Arrayzugriffe machen. Dann wirst Du feststellen, dass da kein wirklich großer Unterschied besteht. Vielleicht ein paar Prozent, aber nichts, was man bei "echtem Code" spürbar merkt.
Echte Performancebremsen sehen in Java anders aus. Zum Beispiel fehlen in der Standardbibliothek Containerklassen für primitive Datentypen. Da kommt man dann schonmal in die Versuchung, die Containerklassen für Objekte mittels der Wrapperklassen für primitive Datentypen zu missbrauchen. Das ist natürlich ein riesiger Overhead, der Zeit und Speicher kostet. ...oder ganz allgemein haben Objekte in Java einen Overhead von 8 Byte pro Objekt. Das ist in C++ so nicht gegeben. Aber man kann sich vorstellen, dass es dann nicht so gut ist, große Mengen, kleiner Objekte in Java zu erzeugen. (...und das hat auch nichts mit dem GC zu tun, der oft für Performenceprobleme verantwortlich gemacht wird, mir persönlich aber noch nie diesbezüglich negativ aufgefallen ist.)
(BTW: Die 8 Byte Overhead pro Objekt haben durchaus eine gewisse Berechtigung. Das ermöglicht Dinge wie Reflection usw.)
Naja, zumindest gibt es schon Eigenschaften von Java, die man kennen sollte, um performanten Code zu schreiben. Das sind aber eher nicht die Dinge, von denen man immer hört, wenn jemand sagt, dass Java unglaublich langsam sei.
BTW: Du kannst unter Java auch ganz bequem mit char-Arrays arbeiten, wenn Du willst. Die Umwandlung von und zu Strings ist da ganz einfach.
-
in schrieb:
das hilft mir wirklich weiter. ich bin nicht der super java crack, aber deine aussagen lassen auch keine besonderen kenntnisse spüren. ich hab geschrieben, das beim zusammenbau der xml struktur die meiste zeit flöten geht. dass das so sein würde, konnte ich auch schon vor der implementierung abschätzen. natürlich habe ich nachgemessen, wer genau wie schuldig ist. und hättest du meine posts richtig gelesen, hättest du das auch gemerkt.
Wenn dir das alles im Vorfeld doch schon so richtig klar war, wie erklärt sich dann dieser Thread? Jetzt schaun wir nochmal an den Anfang zurück:
in schrieb:
Hallo zusammen,
gibts in Java sowas wie inline bei C++? Also um den Methodenrumpf an die rufende Stelle reinzukopieren...
Gruß, in
Uiuiui.
Vielleicht hätte ich es netter ausdrücken sollen, das gebe ich schon zu. Aber dass du tatsächlich im Vorfeld über die tatsächlichen Probleme bescheid wusstest, konnte man bisher nicht so ganz erkennen, auch wenn du inzwischen der Sache schon näher kommst.und falls du noch n beispiel haben willst, wie ich mit einer hashmap elemente einer db verwalten möchte (wenn ich dafür von dir einen _nützlichen_ tipp erhalte), bittesehr:
public HashMap next() throws SQLException{ HashMap erg=new HashMap(); if (!res.next()) return false; int anz=resmeta.getColumnCount(); for( int i=1; i<=anz; i++ ){ erg.put(resmeta.getColumnName(i),res.getString(i)); } return true; }
so hatte ich mir ne connect klasse geschrieben, mit der ich recht angenehm und wiederverwendbar datenbankverwaltung ermögliche. aber das war halt grottenlangsam.
Sieht so aus, als würdest du Spaltennamen als Keys benutzen. Das skaliert recht schlecht bei vielen Elementen, O(n/k), k = Anzahl Spalten der Tabelle € O(n) bei der Suche. Nach Möglichkeit sollten Keys immer sehr unterschiedlich sein, viele unterschiedliche Spaltennamen wirst du nicht haben.
Allerdings weiß ich gar nicht, wie und wie viel du jetzt hier suchst. Damit das optimieren hier etwas bringt, müsstest du erstmal sichergehen, dass die Methoden der Hashmap das langsame sind und dann den Code von den Stellen posten, an denen sie aufgerufen werden. Bis jetzt hast du nur gezeigt, wie du die Hashmap befüllst, aber mir ist noch nicht klar, wie du das dann verwendest. Am besten, du beschreibst mal das typische Szenario, in dem du die Datenstruktur verwendest und was sie dann schnell erledigen können muss, dann finden wir schon das beste heraus.
-
Ich sehe grad, die Hashmap wird nur lokal referenziert und es wird nie aus ihr gelesen. Wofür dient sie überhaupt?
-
Gregor schrieb:
Die Bereichsprüfungen bei Arrays sind auch kein echtes Performanceproblem. Du kannst ja mal ein C++ Programm und ein Java Programm vergleichen, die beide sehr viele Arrayzugriffe machen. Dann wirst Du feststellen, dass da kein wirklich großer Unterschied besteht. Vielleicht ein paar Prozent, aber nichts, was man bei "echtem Code" spürbar merkt.
Ich muss mich korrigieren. Ich habe da gerade ein paar Testprogramme in dieser Art geschrieben und musste feststellen, dass die Unterschiede doch enorm sind. Allerdings nicht immer zu Ungunsten von Java. ...zur allgemeinen Provokation kommt hier mal ein Beispiel, wo Java bei mir deutlich besser abschneidet.
#include <iostream> int main() { const int size = 100000; int *array = new int[size](0); int a = 0; for (int j = 0 ; j < 5 ; ++j) { for (int i = 0 ; i < 2000000000 ; ++i) { array[i%size] += i; } } for (int i = 0 ; i < size ; ++i) { a += array[i]; } delete[] array; std::cout << a << std:: endl; }
vs.
public class ArrayTest { public static void main(String[] args) { final int size = 100000; int[] array = new int[size]; int a = 0; for (int j = 0 ; j < 5 ; ++j) { for (int i = 0 ; i < 2000000000 ; ++i) { array[i%size] += i; } } for (int i = 0 ; i < size ; ++i) { a += array[i]; } System.out.println(a); } }
Ergebnis:
gregor@linux:~/C++Projects/ArrayTest> /usr/java/jdk1.6.0/bin/javac ArrayTest.java gregor@linux:~/C++Projects/ArrayTest> time /usr/java/jdk1.6.0/bin/java -server ArrayTest 1608650240 real 1m13.778s user 1m11.931s sys 0m0.196s gregor@linux:~/C++Projects/ArrayTest> g++ -O3 -o ArrayTest ArrayTest.cpp gregor@linux:~/C++Projects/ArrayTest> time ./ArrayTest 1608650240 real 1m55.157s user 1m54.321s sys 0m0.105s
Keine Ahnung, an was das hier liegt.
-
Eigentlich sollte ein gut (optimal) optimierender Compiler deinen kompletten Quellcode wegoptimieren können (also zur Compilezeit die ganzen Schleifen auflösen und ausrechnen und nur das cout Konstante / System.out Konstante übriglassen).. Von daher könnte das ganze eher auf ein "welcher compiler optimiert besser" vergleich rauslaufen