nordfalk / jsyntaxpane

An updated version of code.google.com/p/jsyntaxpane r096 branch
36 stars 22 forks source link

Performance problem for loading large files (>3MB) - and a fix #196

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Open a large (>3 MB) XML file 
2. The editor freezes in more than 10 seconds

What is the expected output? What do you see instead?
No freeze

What version of the product are you using? On what operating system?
Ubuntu Linux 14.04 

Please provide any additional information below.
The problem is the class SyntaxDocument:

When setText() with a large content is performed this results in that the 
document is re-parsed several thousand times:

at jsyntaxpane.SyntaxDocument.parse(SyntaxDocument.java:65)
at jsyntaxpane.SyntaxDocument.fireInsertUpdate(SyntaxDocument.java:96)
at 
javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:708)
at javax.swing.text.PlainDocument.insertString(PlainDocument.java:130)
at javax.swing.text.DefaultEditorKit.read(DefaultEditorKit.java:273)
at javax.swing.JEditorPane.setText(JEditorPane.java:1415)

The fix I did was to avoid reparsing the document each time fireInsertUpdate is 
invoked. Change:

    @Override
    protected void fireInsertUpdate(DocumentEvent e) {
        parse();
        super.fireInsertUpdate(e);
    }

to

    @Override
    protected void fireInsertUpdate(DocumentEvent e) {
        setNeedsParse();
        super.fireInsertUpdate(e);
    }

    boolean needsParse = false;
    private void setNeedsParse() {
        if (needsParse) return;
        needsParse = true;
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if (!needsParse) return;
                needsParse = false;
                parse();
            }
        });
    }

this filters out the many calls to parse() (which is fast enough by itself) 
from fireInsertUpdate().

Original issue reported on code.google.com by jacob.nordfalk on 28 Apr 2015 at 12:17

GoogleCodeExporter commented 9 years ago
Another fix would be to override the read() method of DefaultEditorKit from

    public void read(Reader in, Document doc, int pos)
        throws IOException, BadLocationException {

        char[] buff = new char[4096];

to use higher block values

    public void read(Reader in, Document doc, int pos)
        throws IOException, BadLocationException {

        char[] buff = new char[409600];

Original comment by jacob.nordfalk on 28 Apr 2015 at 12:19

nordfalk commented 9 years ago

Fixed in https://github.com/nordfalk/jsyntaxpane/commit/ad57ec63c99644ee492cb52ecada6286858aadfd