Laden...

[erledigt] Performance-Problem mit RichTextBox beim Syntax-Coloring (480000 Stellen)

Erstellt von Christoph1968 vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.509 Views
C
Christoph1968 Themenstarter:in
93 Beiträge seit 2007
vor 12 Jahren
[erledigt] Performance-Problem mit RichTextBox beim Syntax-Coloring (480000 Stellen)

Hallo zusammen,

ich stelle u.U. sehr große Textdateien in einer RichTextBox dar.

Das klappt auch sehr gut, das Laden (Einlesen) einer bis zu 60.000 Zeilen umfassenden
Datei dauert weniger als 2 s.
Problematisch wird es nun, wenn ich z.B. bestimmte Textabschnitte (meist einzelne Woerter oder Daten davon) mit einer Hintergrundfarbe versehen will.
Das sind leicht 8 verschiedene Einfaerbungen pro Zeile, also das koennen
bis zu 480.000 Einfaerbungen sein.
Hintergrund: Der Text wird nach bestimmten Mustern durchsucht, die spaeter
als Datenfelder genutzt werden sollen. Durch die Einfaerbung kann man sofort sehen, welches Feld nun welche Bedeutung in einem spaeteren Datensatz bekommen wird. Der Effekt dieser Darstellung ist einfach (atom)bombastisch.

Der Wunde Punkt an dieser Sache ist, dass das Einfaerben der einzelnen Felder
wohl nicht sehr performant ist. Wenn ich das mit den normalen Funktionen der
RichTextBox mache, dauert das leicht eine Minute und teilweise noch viel laenger.
Ich rufe fuer jede Einfaerbung die folgende Funktion auf:


public void highlightText(int startPosition, int length, Color textColor, Color backColor)
                this._richTextBoxSourceFile.Select(startPosition, length);
                this._richTextBoxSourceFile.SelectionColor = textColor;
                this._richTextBoxSourceFile.SelectionBackColor = backColor;
                this._richTextBoxSourceFile.DeselectAll();

Hat jemand (im Gegensatz zu mir) eine Idee, wie man das anderweitig performanter bewerkstelligen koennte ?
Eine Zeitdauer von 10 s bei einer so grossen Datei waere absolut akzeptabel.

Oder bin ich da mit der richTextBox komplett auf dem Holzweg ?
Ich wuerde nur sehr ungerne auf o.g. Effekt verzichten wollen.

Vielen Dank & liebe Grüße

Christoph

C
1.214 Beiträge seit 2006
vor 12 Jahren

Ja, eigentlich bist du auf dem Holzweg. Oder brauchst du wirklich Richtext? Wenn nicht, nimm eine von den viele Syntaxhighlighting Komponenten, z.B. AvalonEdit oder Scintilla. Wenn du doch Richtext brauchst, dann versuche zumindest, die Einfärbung auf Textebene durchzuführen, indem du den RTF Quelltext entsprechend modifizierst, und nicht über die Komponente.

4.938 Beiträge seit 2008
vor 12 Jahren

Hallo Christoph,

ich denke, mit der RTB wirst du es nicht viel schneller hinbekommen.
Evtl. könnte ScintillaNET etwas für dich sein (auch wenn du nur das Styling benötigst).

A
764 Beiträge seit 2007
vor 12 Jahren

Du könntest immer nur den Teil einfärben, der angezeigt wird und/oder du startest einen Hintergrundprozess, der alles einfärbt.

C
Christoph1968 Themenstarter:in
93 Beiträge seit 2007
vor 12 Jahren

Mensch,
Ihr seid ja auf Zack.

Tausend Dank fuer Eure Antworten, da kann ich gleich probieren.

Ich werde berichten.

Nochmals vielen Dank und liebe Grüsse

Christoph

C
Christoph1968 Themenstarter:in
93 Beiträge seit 2007
vor 12 Jahren

Hallo zusammen,

ich habe die gleiche Funktionalitaet mit ScintillaNET implementiert.

Das ist genau das was ich brauche. Das Highlighting von ca. 600.000 Stellen
in einem Dokument mit ca. 10.000 Zeilen benoetigt ca. 5 s.

Und nebenbei kann man auch noch die Zeilennummern einblenden.
Ein total klasse Tool !!!

Vielen Dank fuer Eure Hilfe.

Liebe Grüße

Christoph

C
1.214 Beiträge seit 2006
vor 12 Jahren

Warum dauert das so lang? Wie genau machst du das? Ich denke, das kann man noch gut optimieren, 5s kommt mir jetzt etwas lang vor...

C
Christoph1968 Themenstarter:in
93 Beiträge seit 2007
vor 12 Jahren

Hallo Coder 007,

vielen Dank fuer Deine Antwort.
Ich habe einen ScreenShot der Editorkomponente meines Programmes
angehaengt. Ich definiere einen mehr oder weniger komplexen regex,
der verschiedene benamte Gruppen enthaelt. Die Gruppennamen im Regex werden mit einer Farbe gekennzeichnet. Mit genau dieser Farbe werden dann auch die gefundenen Uebereinstimmungen in Scintilla hervorgehoben.
Bei geschachtelten Gruppen wird jede Uebereinstimmung buchstabenweise abwechselnd mit den Farben der geschachtelten Gruppen hervorgehoben.
Das braucht vermutlich am meisten Resourcen.

Fuer jede Hervorhebung wird eine Schleife Schleife durchlaufen
die folgende Funktion aufruft:

/// <summary>
        /// Highlights a selection of the text in the scintillaTextBox
        /// </summary>
        /// <param Name="startPosition">Start-position of the highlighting</param>
        /// <param Name="length">Length of the text to be highlighted</param>
        /// <param Name="textColor">Color of the text</param>
        /// <param Name="backColor">Color of the background</param>
        public void highlightText(int startPosition, int length, Color textColor, Color backColor)
        {
            try
            {
                if (!_dictionaryScintillaStyles.ContainsKey(backColor.Name + "-" + textColor.Name))
                {
                    _dictionaryScintillaStyles.Add(backColor.Name + "-" + textColor.Name, _dictionaryScintillaStyles.Count + 20);
                    _scintillaTextBox.Styles[_dictionaryScintillaStyles[backColor.Name + "-" + textColor.Name]].BackColor = backColor;
                    _scintillaTextBox.Styles[_dictionaryScintillaStyles[backColor.Name + "-" + textColor.Name]].ForeColor = textColor;
                }
               
                _scintillaTextBox.Styles[_dictionaryScintillaStyles[backColor.Name + "-" + textColor.Name]].Apply(startPosition, length);
            }
            catch
            {

            }

        }//public void highlightText(int startPosition, int length, Color textColor, Color backColor)

Wenn ich die Hervorhebung umgehe, indem ich sofort nach diesem Funktionsaufruf mit return beende, dauert der Rest der Schleife ca. 1.5 s.
Mit Hervorhebung dauert das ca. 5.5 s. Das heisst, das fuer die reine Hervorhebung ca. 4 s benoetigt werden.

Siehst Du da noch Potential ?

Viele Grüße

Christoph

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo Christoph1968,

Bei geschachtelten Gruppen wird jede Uebereinstimmung buchstabenweise abwechselnd mit den Farben der geschachtelten Gruppen hervorgehoben.

ich würde die Farbe inneren Gruppe gewinnen lassen. Matchen beide Gruppen exakt gleichlang, wie im Beispiel, ist automatisch klar dass die innere Farbe auch für die äußere steht. Matcht die innere Gruppe kürzer, bekommt man mit äußere Farbe, innere Farbe, äußere Farbe auch ein plausibles Ergebnis. So habe ichs bei On-the-fly Regex-Tester: Regex-Lab gemacht (wobei Regex-Lab zum Testen gedacht und nicht optimiert auf große Datenmengen ist).

herbivore

4.938 Beiträge seit 2008
vor 12 Jahren

Hallo Christoph,

noch ein kleiner Optimierungshinweis: benutze einen lokalen String zum Zugriff auf den Namen (anstatt ihn immer wieder temporär erzeugen zu lassen):


string name = backColor.Name + "-" + textColor.Name;

(kann aber auch sein, daß der Jitter dies automatisch wegoptimiert - ich selber würde mich aber nicht darauf verlassen 😉

Und super, daß der Umstieg auf ScintillaNET bei dir so schnell geklappt hat!

C
Christoph1968 Themenstarter:in
93 Beiträge seit 2007
vor 12 Jahren

Hallo zusammen,

also zu aller erst ganz vielen lieben Dank fuer Euer Engagement.
Kann ich nur sagen, Hut ab.

@herbivore: Ja, das mit der innersten Gruppe war auch mein erster Ansatz, aber die User kamen damit nicht zurecht und ich habe es nicht hinbekommen, das so zu kommunizieren, dass das funtioniert haette.
Dann habe ich das wie oben beschrieben modifiziert, womit die Leute dann zwar einerseits leichter zurechtkamen,
andererseits hat dies im Gegenzug die Performanceprobleme mit der RichTextBox manchmal ins Unertraegliche gesteigert. Mit ScintillaNET macht diese Anwendung einen rieeeeeeesigen Schritt nach vorne.
Und was RegexLab betrifft: Seit ich es kenne, gehoert es zu meinen Standard-Tools, und wenn ich mich recht erinnere war es Dein RegexLab, das mich in diesem Projekt zu diesem graphisch unterstuetzten Loesungsansatz animiert hat.

@Th69: Vielen Dank auch Dir. Solche Schoten schreibe ich öfter. Ich weiss eigentlich auch nicht, warum.Klar, das ist besser,
es nicht 3 x neu zu generieren.

Euch ein schoenes Wochenende & liebe Grueße

Christoph