SWT Performance : "Text" - Ausgabe beschleunigen ?

Status
Nicht offen für weitere Antworten.

pocketom

Bekanntes Mitglied
Hallo,
ich habe eine kleine Anwendung die überwiegend verschiedene Dinge in einem großen Textfenster ausgibt. Hauptsächlich werden dort Sachen aufgelistet, die Daten dazu werden aus einem Vektorcontainer gelesen. Oftmals wird dabei auf mehr als 500 Datenobjekte zugegriffen, es entstehen i.d.R. Logs in Tabellenform. Meine Ausgabe hatte ich bis jetzt ganz simpel in der Console nach dem Schema:
Code:
while(myiterator.hasnext()) 
     System.out.println(myiterator.next().getMyText());
Das geht auf der Konsole eigentlich sehr flott, der Zugriff auf den Datencontainer an sich ist also offenbar schnell genug(sicher kann man statt Vector auch hier noch was schnelleres nehmen...).


Nun mache ich im Prinzip genau das gleiche in meiner kleinen SWT Gui Anwendung:
Code:
Text logwindow = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);

while(myiterator.hasnext()) 
     logwindow.append(myiterator.next().getMyText()+"\n");

Das ganze dauert ewig, vor allem sieht man während der Verarbeitung keinen Fortschritt obwohl ich "append" benutze. Das Ergebnis, also z.B. 500 Zeilen "Bla Bla", wird am Ende auf einen Schlag angezeigt anstatt es zeilenweise aufzubauen. In der Konsole hingegen wird während die while Schleife noch läuft wird immer sofort die Ausgabe der jeweiligen Zeile gemacht.

Wie krieg ich das in meinem SWT Fenster hin, zumindest so das der Benutzer zusehen kann während sein log erstellt wird und man nicht nach ner halben Minute denkt das Programm wäre abgestürzt...?
 

byte

Top Contributor
Du solltest Berechnungen nicht im Event-Dispatching-Thread der GUI machen, weil das GUI sonst in der Zeit blockiert. Pack die Iteration also in einen eigenen Thread und kapsel die Zugriffe auf die GUI dann in ein Runnable und übergib dies an die Display#asyncExec(). Das ist nötig, weil SWT es verbietet, von einem anderen Thread schreibend auf die GUI zuzugreifen. Also in etwa so:


Code:
display.asyncExec(new Runnable() {
  public void run() {
    text.append(...);
  }
});
 
G

Guest

Gast
Alles klar, danke! Ich probiers morgen gleich mal aus und meld mich nochmal wenns Probleme gibt. Bis jetzt habe ich es so das die Iterationen in einer eigenen Printfunktion laufen der man die Referenz zum Textfeld mitgeben kann(void printOutput(Text texbox))

Das würde ich also jetzt so machen?:

Code:
class myDataClass{


    ...
    ...
    ...

    public void printOutput(Display display, Text texbox)
    {

            ...
            ...
            ...

            display.asyncExec(new Runnable() { 
                  public void run() { 

                        while(myiterator.hasnext()) 
                             textbox.append(myiterator.next().getMyText()+"\n");
                 } 
            });
    }
}

 :?:
 

Wildcard

Top Contributor
Code:
textbox.append(myiterator.next().getMyText()+"\n");
Das ist deine Performancekrücke.
Nimm einen StringBuilder.
 

pocketom

Bekanntes Mitglied
Was mich am "display.asyncExec(new Runnable()....." stört ist das ich meine Variablen die ich an die Funktion übergebe alle im Funktionskopf final machen muss. Sämtliche Berechnungen muss ich dann ausserhalb meiner Funktion machen, was mir die Kapselung im Prinzip zunichte macht... Kann man das nicht noch irgendwie anders lösen?
 

pocketom

Bekanntes Mitglied
Hi, den StringBuilder hab ich eingebaut und verwende ihn analog zu meiner Textbox:

Code:
StringBuilder strb = new StringBuilder();

...
...

while(myiterator.hasnext())
                             strb.append(myiterator.next().getMyText()+"\n");


Wie mache ich dass das ich keine anonyme innere Klasse benutze? Ich habe alles mögliche probiert, aber diese Konzepte kenne ich irgendwie nicht. :bahnhof:

Code:
public void myFunction(Display display, int myValue){
		display.asyncExec(new Runnable() {
                     public void run() {
                                 myValue++;               
           }
      });
kannst du mir das vielleicht anhand meines kleinen Beispiels kurz erklären? Mir fehlt irgendwie der entscheidende Denkanstoß ???:L
 

Wildcard

Top Contributor
Code:
strb.append(myiterator.next().getMyText()+"\n");
Der gleiche Mist. In einer Schleife die häufig durchlaufen wird darf es kein String + String geben.
Was für ein Beispiel denn? Du wirst doch wissen wie man eine Klasse schreibt die Runnable implementiert? ???:L
 

pocketom

Bekanntes Mitglied
Hi. Ich verstehe nicht wie ich es sonst machen soll. Die Schleife wird nunmal häufig durchlaufen, trotzdem muss alles in der Textbox ausgegeben werden, ich versteh nicht ich es sonst machen soll... :bahnhof:

Muss ich jetzt für alles was ich in meiner Textbox ausgeben will eine neue Klasse schreiben die Runable implementiert???
 

pocketom

Bekanntes Mitglied
Sorry das ich nochmal fragen muss, aber es ist dringend und ich komme leider auf keine bessere Lösung

In einer Schleife die häufig durchlaufen wird darf es kein String + String geben.

Wie umgehe ich das Problem in meinem Fall am geschicktesten? Ich habe wiegesagt keine Möglichkeit die Schleife abzuschaffen, ich brauche von einigen hundert Objekten je eine Zeile Ausgabe, so dass am Ende im Textfeld auch einige hundert Zeilen stehen. Wie ich das nicht in einer Schleife hinkriegen soll ist mir ein Rätsel, ich muss schliesslich alle Objekte durchgehen. Das während dem Schleifendurchlauf in den Stringbuilder zu stecken erfordert ja auch ein "append" o.Ä., also was soll ich machen ???:L :bahnhof: :cry:
 

byte

Top Contributor
Einfach zweimal appenden statt + Operator:
Code:
strb.append(myiterator.next().getMyText());
strb.append("\n");

Was mich am "display.asyncExec(new Runnable()....." stört ist das ich meine Variablen die ich an die Funktion übergebe alle im Funktionskopf final machen muss. Sämtliche Berechnungen muss ich dann ausserhalb meiner Funktion machen, was mir die Kapselung im Prinzip zunichte macht... Kann man das nicht noch irgendwie anders lösen?

Deine Kapselung ist eh etwas komisch, wenn ich mir den Code weiter oben angucke. Mach den asyncExec() Aufruf nicht in diese Function, sondern dort, wo die GUI aktualisiert wird. Und vergiß nicht, dass ganze aus einem neuen Thread aufzurufen, sonst hast Du nichts gewonnen. Also Deine Schleife muss in einem eigenen Thread laufen. Und nur die Zeile, wo Du aus diesem Thread Deine GUI aktualisierst, muss über asyncExec() laufen.
 

pocketom

Bekanntes Mitglied
Einfach zweimal appenden statt + Operator:
Argh, sorry da war ich wohl blind. Da muss man erstmal drauf kommen. Ich dachte bis jetzt das "+" eh das selbe tut wie "append" ...

Und vergiß nicht, dass ganze aus einem neuen Thread aufzurufen, sonst hast Du nichts gewonnen. Also Deine Schleife muss in einem eigenen Thread laufen.

Das mit dem asyncExec und den Threads versteh ich leider immer noch nicht so 100%. Ich habe noch nie damit gearbeitet. Weist du vielleicht einen Link wo man sich das mal an einem kleinen Beispiel ansehen kann? Zu Threads hab ich zwar tausende gefunden, aber wie ich das jetzt bei mir am geschicktesten mit dem asyncExec, dem Stringbuilder und meiner GUI kombiniere hab ich immer noch ned so raus. Irgendwie hab ich wohl ein bischen den Überblick verloren. Aber ich programmiere ja auch erst seit zwei monaten Java... :lol:
 

byte

Top Contributor
Die SWT GUI läuft in einem Thread, der auch die Events verarbeitet (Event Dispatcher), also z.B. das Verändern der Fenstergröße oder das Drücken eines Knopfes. Nun lässt Du rechenintensive Berechnungen ebenfalls in diesem Thread ablaufen (in Deinem Fall wohl die Schleife mit dem StringBuilder). Diese Berechnungen blockieren nun die GUI, so dass es zu Verzögerungen beim Event-Dispatching kommt. So wird z.B. die GUI nicht richtig aktualisiert, weil einfach nicht genug Rechenzeit zur Verfügung steht.

Die Lösung: Rechenintensive Operationen gehören nicht in den Event-Dispatch-Thread, sondern in einen eigenen Thread. Das heisst, Du musst zunächst erstmal einen neuen Thread erzeugen und dort Deine Schleife machen (wie man mit Threads umgeht, ist in einem beliebigen Java-Grundlagenbuch nachzulesen).

Nun möchtest Du natürlich auch Deine GUI mit den berechneten Daten aktualisieren. Da wirft SWT eine Exception, wenn Du dies über einen anderen Thread als den Event-Dispatcher versuchst. Warum? Weil es so zu Race-Conditions und inkonsistenten Verhalten kommen kann, wenn man nebenläufig schreibend auf GUI Komponenten zugreift.

Lösung: Display.asyncExce() oder Display.syncExec() verwenden. Diese Methoden übergeben die Anfrage an den Event-Dispatcher, der sie nacheinander ausführt. Die Methoden verlangen ein Runnable, die man ohne weiteres als anonyme Objekte implementieren kann.

Wenn Du also aus einem zweiten Thread dem Text-Widget etwas hinzufügen willst, dann musst Du das in etwa so machen:

Code:
// irgendwo in einem anderen Thread
// statt 'text.append("hallo");' nun einfach folgendes:
Display.asyncExec(new Runnable() {
  public void run() {
    text.append("hallo");
  }
});
 

pocketom

Bekanntes Mitglied
Super, klasse und vielen Dank! Jetzt wird mir das langsam klrer. Denke ich werds jetzt hinbekommen. Vielen Dank nochmal!
 

pocketom

Bekanntes Mitglied
Hi, das mit der Performance haut mittlerweile ganz gut hin, der Stringbuilder hat das ganze um ein vielfaches beschleunigt. Allerdings klappts mit dem Echtzeitoutput im Textfeld immer noch nicht, die Anfrage wird erst nachdem sie bearbeitet wurde auf einen Schlag angezeigt, und nicht so wie gewünscht schon während der Berechnung parallel aktualisiert (trotz display.asyncExec() )

Ich bin wie folgt vorgegangen:


Code:
public class PrintString implements Runnable {
	
	Display display;
	Text textbox;

	
	// Constructor
	public PrintString(Display display, Text textbox)
	{
		super();
		this.display = display;
		this.textbox = textbox;
				
		this.run();
	}	
	
	public synchronized void run()
	{			
		final StringBuilder strb = new StringBuilder();
		
		...
		...
		...
		
			
		while(readings_iterator.hasNext())
		{
			// fetch current object into temporary read-object
			temp = (SingleRead) readings_iterator.next();
							
			strb.append("Sequence:				");
			for(int i=0;i<temp.getHeader().getNumber_of_bases(regfile.getFileHeader().getKey_length(),taglength);i++)
			{
				strb.append(temp.getData().getBase(i, regfile.getFileHeader().getKey_length(), taglength,  false, false));
				strb.append("\t");
			}
			strb.append("\n");			
				
			
			// send result to textbox immediately
			// clear the stringbuilder
			display.asyncExec(new Runnable() {
					  public void run() {
						  textbox.append(strb.toString());
						  strb.delete(0, strb.length());
					  }
				});				
		}			
	}		
}
geht wiegeagt halbwegs flott, aber ich hätte jetzt erwartet das in jedem Schleifendurchlauf der gerade generierte String im Textfeld ausgegeben wird ? Mache ich noch irgendwas falsch?
 

byte

Top Contributor
Hm komisch. Habs in ähnlicher Form in einem Projekt und da gehts einwandfrei. Hast Du es mal mit Display.syncExec() probiert? Oder mal explizit textbox.update() machen nach dem Append.
 

pocketom

Bekanntes Mitglied
Wenn ich "Display" groß schreibe bringt Eclipse den Fehler:
Cannot make a static reference to the non-static method asyncExec(Runnable) from the type Display

textbox.update() habe ich mit in die asynExec reingepackt, hat aber leider auch null Effekt :bahnhof:
 

byte

Top Contributor
Ändere mal asyncExec(...) in syncExec(...) in Deinem Code. Ansonsten fällt mir auch nix mehr ein. Bei mir gehts wie gesagt einwandfrei.
 

byte

Top Contributor
Hm, sehr merkwürdig. Du hast nicht zufällig irgendwo bei der Textbox setRedraw(false) gesetzt?

Du könntest am Anfang oder Ende der While-Schleife mal ein yield() einfügen. Kann mir aber kaum vorstellen, dass das was ändert. Ansonsten poste nochmal den aktuellen Code. Am besten auch die Stelle, wo Du das Text-Widget erzeugst.
 

pocketom

Bekanntes Mitglied
Hi, hab das ganze im Moment wieder rausgeschmissen. Ich werde es bei Gelegenheit mal an einem kleinen beispiel nochmal probieren. Der Code ist schon recht mächtig, und das immer so zusammenzuschneiden damits hier reinpasst macht mir zuviel Arbeit. Ich denke an einem kleinen Minibeispiel kommt das durchschaubarere. Ich poste es auf jeden Fall sobald ich es habe, obs dann geth oder nicht...
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
H Viele ActionListener (MouseListener) - Performance AWT, Swing, JavaFX & SWT 24
missy72 JavaFX Performance / ImageView in TableView über TimeLine AWT, Swing, JavaFX & SWT 1
L JavaFX ListCell Performance AWT, Swing, JavaFX & SWT 10
E Swing Miserable Performance beim Ändern der Hintergrundfarbe von JLabels AWT, Swing, JavaFX & SWT 3
W Swing Performance bei Griderstellung verbessern AWT, Swing, JavaFX & SWT 15
C Pixel-Rendering/Animation Performance in BufferedImage AWT, Swing, JavaFX & SWT 1
I JavaFX Graphics Performance AWT, Swing, JavaFX & SWT 2
S Swing Performance bei Verschachtelung problematisch AWT, Swing, JavaFX & SWT 0
R Performance Drag and Drop & Timer AWT, Swing, JavaFX & SWT 3
O AWT Performance und Bug behebung[brauche Hilfe] AWT, Swing, JavaFX & SWT 2
T Swing Allgemeines Problem mit der Performance bei DragAndDrop AWT, Swing, JavaFX & SWT 2
T Prüfen ob 2 JLabel übereinander liegen. Performance Problem. AWT, Swing, JavaFX & SWT 5
S Swing Lauftext Performance Probleme, in größerer Anwendung AWT, Swing, JavaFX & SWT 6
B Performance-Probleme AWT, Swing, JavaFX & SWT 17
D DefaultTableCellRenderer - Performance AWT, Swing, JavaFX & SWT 3
hdi Swing [Umfrage] Swing Performance AWT, Swing, JavaFX & SWT 27
B 2D-Grafik BufferedImage Performance AWT, Swing, JavaFX & SWT 3
C Performance-Problem beim Überschreiben von paintComponent() AWT, Swing, JavaFX & SWT 2
Hausmeister JTable mit Bildern - Performance AWT, Swing, JavaFX & SWT 5
J JTree Performance AWT, Swing, JavaFX & SWT 2
Developer_X Swing Graphics2D translate zerstört performance AWT, Swing, JavaFX & SWT 2
hdi Swing JTable: Mein CellRenderer ist ein Performance-Killer? AWT, Swing, JavaFX & SWT 7
J Performance bei mouseMoved(...) AWT, Swing, JavaFX & SWT 4
L JFreeChart - Performance bei PNG-Erstellung AWT, Swing, JavaFX & SWT 5
P seltsame Performance Probleme bei 2 Guis abhängig vom Aufruf AWT, Swing, JavaFX & SWT 8
G Performance beim Zeichnen erhöhen? AWT, Swing, JavaFX & SWT 21
hdi bitte um performance ratschläge AWT, Swing, JavaFX & SWT 31
G performance fragen zu AWT, Swing AWT, Swing, JavaFX & SWT 14
T (Java 6) Thumbnails in JFileChooser - Performance steigern? AWT, Swing, JavaFX & SWT 3
hdi schlechte performance bei simplem swing AWT, Swing, JavaFX & SWT 9
G Probleme mit Performance bei einer Tabelle AWT, Swing, JavaFX & SWT 16
M Performance SWT ??? AWT, Swing, JavaFX & SWT 8
D performance problem: paintcomponent, alphacomp, bufferedImag AWT, Swing, JavaFX & SWT 10
P SWT: StyledText Performance steigern? AWT, Swing, JavaFX & SWT 2
T Performance Problem bei BufferedImage AWT, Swing, JavaFX & SWT 3
O performance g2d.drawImage() AWT, Swing, JavaFX & SWT 17
D Performance Probleme Jtable AWT, Swing, JavaFX & SWT 4
N Performance (BufferStrategy?) AWT, Swing, JavaFX & SWT 2
F Problem mit Transparenz, MouseEvents und Performance AWT, Swing, JavaFX & SWT 3
O LookAndFeel und Performance AWT, Swing, JavaFX & SWT 7
W Performance verbessern AWT, Swing, JavaFX & SWT 2
S TableCellRenderer, Performance AWT, Swing, JavaFX & SWT 9
S Performance-Problem: JTextArea als Logging-Window AWT, Swing, JavaFX & SWT 8
P JTextfield Text durch Keylistener verändern AWT, Swing, JavaFX & SWT 4
G Problem mit der Anzeige von jLabel. Unlesbar wenn der Text geändert wird. AWT, Swing, JavaFX & SWT 28
C JToggleButton disabled Text Color AWT, Swing, JavaFX & SWT 11
H JavaFX Label.Text mit bind an DoubleProperty binden AWT, Swing, JavaFX & SWT 3
H JList.setEnabled(false) - Text soll nicht grau sein AWT, Swing, JavaFX & SWT 2
FrittenFritze Text in Flying Saucer selectierbar machen AWT, Swing, JavaFX & SWT 0
Mojo7310 Ändern von Text in JLabel mit einem Button AWT, Swing, JavaFX & SWT 11
raeuchertofu Text von JTextfield und JLabel ändern AWT, Swing, JavaFX & SWT 2
H JavaFX Gedrehter Text auf Canvas (Positionierung) AWT, Swing, JavaFX & SWT 6
F Best-Practise: JTable Text in Zelle zu groß AWT, Swing, JavaFX & SWT 2
I Rich Text drucken AWT, Swing, JavaFX & SWT 0
B Text mit Absatz + OK-Button, der Fenster wieder schließt AWT, Swing, JavaFX & SWT 7
R Text vom Jlabel wird nicht angezeigt AWT, Swing, JavaFX & SWT 2
N Promt Text der Combobox AWT, Swing, JavaFX & SWT 0
M JavaFX javaFX Label-Text wird nicht gesetzt AWT, Swing, JavaFX & SWT 3
sascha-sphw JavaFX ListCell höhe verändert sich beim ändern der Text-Farbe AWT, Swing, JavaFX & SWT 14
N In Textdatei Text anfügen per GUI AWT, Swing, JavaFX & SWT 3
N Textdatei GUI, Text in Textarea anzeigen mehrere Zeilen AWT, Swing, JavaFX & SWT 1
R Swing JTextField nicht-kopierbarer Text AWT, Swing, JavaFX & SWT 1
S Text-Info in der Taskbar anzeigen AWT, Swing, JavaFX & SWT 15
E Warum wird Text im JTextArea erst am Programmende angezeigt ? AWT, Swing, JavaFX & SWT 1
S Swing JLabel Text mit der Zeit ändern AWT, Swing, JavaFX & SWT 1
Hatsi09 JButton text layout AWT, Swing, JavaFX & SWT 9
B Text im Tetfeld in einer TableView darstellen AWT, Swing, JavaFX & SWT 20
C JCheckBox disabled text color AWT, Swing, JavaFX & SWT 9
ralfb1105 JavaFX Wie Text Label in neuem Window von Main Stage setzen? AWT, Swing, JavaFX & SWT 6
CptK Swing Button: ImageIcon unter den Text AWT, Swing, JavaFX & SWT 4
K Swing Text eines Lables in einer Methode ändern AWT, Swing, JavaFX & SWT 13
L JavaFX TableView kein content text ändern AWT, Swing, JavaFX & SWT 2
L JavaFX Anderer Text, wenn kein Platz ist. AWT, Swing, JavaFX & SWT 1
K JavaFX TextInputDialog Button Text ändern AWT, Swing, JavaFX & SWT 1
S 2D-Grafik affine Transformation für Text-Shape AWT, Swing, JavaFX & SWT 0
B JavaFX Text wird nicht angezeigt, kein Fehler AWT, Swing, JavaFX & SWT 2
J Text in ein Textfeld eingeben und speichern AWT, Swing, JavaFX & SWT 27
xYurisha JLabel Text einer geöffneten Gui über eine andere Klasse ändern! AWT, Swing, JavaFX & SWT 3
C Swing Spinner als TableCellEditor - Text zu klein AWT, Swing, JavaFX & SWT 2
H JavaFX - Button und Text - Falsche Darstellung AWT, Swing, JavaFX & SWT 3
DaCrazyJavaExpert Swing Extern den Text eines nicht fetsgelegten Buttons bekommen. AWT, Swing, JavaFX & SWT 12
zhermann FX Label text wird nicht richtig angezeigt AWT, Swing, JavaFX & SWT 12
I JavaFX formatierter Text in PDF speichern AWT, Swing, JavaFX & SWT 4
T JavaFX Text des ProgressIndicators ändern AWT, Swing, JavaFX & SWT 2
E Swing Text verschwindet AWT, Swing, JavaFX & SWT 1
G JavaFX - Während AudioRecording keine Text eingabe TextField möglich AWT, Swing, JavaFX & SWT 6
G Rectangle Breite richtet such an die Breite vom Text AWT, Swing, JavaFX & SWT 1
Sanni94 JavaFX Kann man eine Grafik in einen Text einbinden? AWT, Swing, JavaFX & SWT 2
S JTextArea Text nach oben wandern lassen AWT, Swing, JavaFX & SWT 7
F Icons neben Text in Listview setzen AWT, Swing, JavaFX & SWT 2
K Rich Text FX von TomasMikula AWT, Swing, JavaFX & SWT 0
M Text in einem Label fett setzen AWT, Swing, JavaFX & SWT 4
S JAVAFX HTMLEditor wrap text AWT, Swing, JavaFX & SWT 1
J JavaFX Translation Text/Label AWT, Swing, JavaFX & SWT 2
K Swing JTable mit ImageIcon und Text in einer Zelle AWT, Swing, JavaFX & SWT 1
A JavaFX HTMLEditor in Text umwandeln AWT, Swing, JavaFX & SWT 2
M Swing jButton Text verschwindet AWT, Swing, JavaFX & SWT 2
J JavaFX Bestimmte Zellen im TableView ändern (Farbe und Text) AWT, Swing, JavaFX & SWT 1
2 JLabel - setText ändert den Text nicht AWT, Swing, JavaFX & SWT 4
B Jlabel Text von anderen Klasse aus ändern AWT, Swing, JavaFX & SWT 9

Ähnliche Java Themen

Neue Themen


Oben