1

I am trying to implement JLanguageTool in combination with JavaFX and RichtextFX to get myself a GUI which spellchecks the given input in a Codearea and highlights misspelled words. My problem is, that even for small sentences (6 words) with a little amount of misspells (3 misspells) my program takes 10-12 seconds to execute(only the spellchecking part). I've already tried optimizing my program by deactivating rules that are not neccessary for me. Here's my code:

import org.languagetool.JLanguageTool;
import org.languagetool.language.GermanyGerman;
import org.languagetool.rules.Category;
import org.languagetool.rules.CategoryId;
import org.languagetool.rules.RuleMatch;

import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class LanguageToolTest {

    private static JLanguageTool tool = new JLanguageTool(new GermanyGerman());

    public static void prepareRule(){
        Map <CategoryId, Category> akku = tool.getCategories();
        for (var entry : akku.entrySet()){
            if (!entry.getKey().toString().contains("EMPFOHLENE_RECHTSCHREIBUNG")
            && !entry.getKey().toString().contains("CASING")
            && !entry.getKey().toString().contains("TYPOS")
            && !entry.getKey().toString().contains("COMPOUNDING")
            && !entry.getKey().toString().contains("PUNCTUATION")
            && !entry.getKey().toString().contains("CONFUSED_WORDS")
            && !entry.getKey().toString().contains("SEMANTICS")){
                tool.disableCategory(entry.getKey());
            }
        }
    }

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

        Instant start = Instant.now();
        Map<Integer, List<String>> test = new HashMap<>();
        int index = 0;
        try {
            List<RuleMatch> matches = tool.check("Heilike makrele hier ist echter Tecst");
            for (RuleMatch match : matches){
                List<String> temp = new ArrayList<>();
                index = match.getFromPos();
                int end = match.getToPos();
                String idk = "Heilike makrele hier ist echter Tecst".substring(index, end);
                temp.add(idk);
                temp.addAll(match.getSuggestedReplacements());
                test.put(match.getFromPos(), temp);
            }
            Instant stop = Instant.now();
            Duration timeElapsed = Duration.between(start, stop);
            System.out.println(test.toString());
            System.out.println("Hat " + timeElapsed.toMillis() + " Millisekunden gedauert.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

And the output:

{0=[Heilike, Heilige, Heiligen, Heidecke, Heilig, Heinicke, Heiliger, Heiliges, Heiligem, Beilage, Heiligt, Heike, Heiligte, Fällige, Herlocke, Heutige, Wellige, Heftige, Eilige, Häufige, Seidige], 32=[Tecst, Eckt, Deckt, Test, Täks, Deckst, Erst, Teast, Lässt, Des, Meist, Fest, Heißt, Jetzt, Setzt, Weist, Recht, Text, West, Wächst, Geist], 8=[makrele, Makrele, makele, mäkele, sakrale, magere, mangele, Makrelen, Nägele, Häcksel, Häckseln, angele, dackele, fackele, fächele, hagele, häckseln, häkele, lächele, magerere, magerte]}
Hat 12483 Millisekunden gedauert.

To explain the Map: my Key stores the start index of the found error for further processing and the List value stores a list of the misspelled word at index 0 and recommended replacements on the following indecies.

In my actual code the Map gets returned and processed for the highlighting part.

As far as I understood the documentation of JLanguageTool it's not thread-safe therefore I can't multithread it.

Any suggestions on how to improve my code/optimize certain calls to reduce the performance impact?

  • 1
    use a profiler to find the bottleneck – kleopatra Jan 19 '22 at 13:59
  • @kleopatra I have none installed and have no clue how to use one – Michael Fuchs Jan 19 '22 at 14:40
  • 1
    then install one and learn how to use it :) There is no other way to find the reason for performance problems - without measuring, it's reading in cloudy crystal balls .. – kleopatra Jan 19 '22 at 15:15
  • 2
    The tool is [expected to be slow if you use it without warming it uo](https://github.com/languagetool-org/languagetool/blob/master/languagetool-standalone/src/main/java/org/languagetool/gui/LanguageToolSupport.java#L312). – jewelsea Jan 19 '22 at 16:21
  • `jconsole`, _J2SE Monitoring and Management Console_, may be included with your JDK. – trashgod Jan 19 '22 at 18:42
  • I do not know about the threading model for JLanguageTool, but you may want to use the JavaFX [concurrent](https://openjfx.io/javadoc/17/javafx.graphics/javafx/concurrent/package-summary.html) package to interface with it rather than invoking it directly on the JavaFX application thread. – jewelsea Jan 20 '22 at 01:00
  • My advice is to first look into the warmup issue for JLanguageTool by running the warmup in a separate background thread when the app starts and before you need to spell check anything and ensure that you don't have it do a warmup every time you run a spell-check. – jewelsea Jan 20 '22 at 01:01
  • The free [VisualVM tool](https://visualvm.github.io/index.html) can be used for profiling, there is documentation at the VisualVM site and other articles about it on the web. Profiling is a skill and takes some study, time, and effort to learn to do reasonably well. – jewelsea Jan 20 '22 at 01:01
  • Does this answer your question? [JavaFX Spell checker using RichTextFX how to create right click suggestions](https://stackoverflow.com/questions/72204764/javafx-spell-checker-using-richtextfx-how-to-create-right-click-suggestions) – trilogy May 19 '22 at 01:29
  • @trilogy sadly no, the spellchecking used in this question was implemented by themselves. I am using the JLanguageTool Library – Michael Fuchs Jun 17 '22 at 14:32
  • @MichaelFuchs when does the spell checking execute? What I was able to do was to have a separate thread populate a Map of "Incorrect words" to a list of "Suggestions". This happens on a separate thread as it finds incorrect words. By the time the user right-clicks an incorrect word, the suggestion has already been pre-populated. Even if JLanguageTool is not thread-safe, as long as you don't use it in your main thread, the background thread can pre-populate a `ConcurrentHashMap` of suggestions. – trilogy Jun 20 '22 at 13:33

0 Answers0