FXMisc / RichTextFX

Rich-text area for JavaFX
BSD 2-Clause "Simplified" License
1.21k stars 236 forks source link

Surprisingly slow when adding text one character at a time. #112

Closed ghost closed 9 years ago

ghost commented 9 years ago

Hi! I want to use RichTextFX in a Telnet client sort of setup. Right now I handle one character at a time (debatable, I want to show things as soon as they become available, even if it's part of a line, but should be possible right? :) ). And it turns out when doing that, things get Very slow.

I prepared a standalone sample, which fills just a few screens of text, and takes several seconds to do so. Even tho I'm being inefficient, I don't think it should take this long? :)

Note: It could well be I'm using things wrong, feel free to tell me what if so :)

Thanks for any attention in advance!

import java.io.IOException;
import java.security.SecureRandom;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.fxmisc.richtext.CodeArea;

public class CopyOfJavaKeywords extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws IOException {

        // Create some test data.
        final StringBuilder builder = new StringBuilder();
        final SecureRandom random = new SecureRandom();
        for (int line = 0; line < 24 * 5; line++) {
            for (int charPos = 0; charPos < 80; charPos++) {
                builder.append((char) ('A' + random.nextInt('Z' - 'A')));
            }
            builder.append("\n");
        }
        final byte[] testData = builder.toString().getBytes();

        // Setup the scene
        final CodeArea codeArea = new CodeArea();
        final Scene scene = new Scene(new StackPane(codeArea), 600, 400);
        primaryStage.setScene(scene);
        primaryStage.show();

        // Start a thread which feeds characters to the code area, one by one.
        final Thread thread = new Thread(() -> {
            System.out.println("Start..");
            for (byte input : testData) {

                Platform.runLater(() -> {
                    codeArea.appendText("" + (char) input);
                });
            }
            System.out.println("Done..");
        });
        thread.setDaemon(true);
        thread.start();

    }
}
TomasMikula commented 9 years ago

You're right, it shouldn't be this slow. Hopefully I will have a chance to look into it over the weekend. I have an idea how to improve it.

ghost commented 9 years ago

Awesome, thanks :) I hope to have more use-full reports as I mess more with it ^.^

TomasMikula commented 9 years ago

0.6.1 has improved performance. Let me know how it works for you. While the sample you posted is on my machine still about 3x slower with CodeArea than with TextArea, I consider it resolved.

ghost commented 9 years ago

Yup, performance is greatly improved as far as I can tell, much better! :) Great job ^_^