AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Desaströse Performance von TRichedit

Ein Thema von Maekkelrajter · begonnen am 11. Sep 2024 · letzter Beitrag vom 12. Sep 2024
Antwort Antwort
Seite 1 von 3  1 23      
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
156 Beiträge
 
Delphi 12 Athens
 
#1

Desaströse Performance von TRichedit

  Alt 11. Sep 2024, 15:03
Wie es scheint, ist die ohnehin noch nie berauschende Performance des TRichedit-Controls ist seit Delhpi 11 geradezu ins bodenlose gesackt. Bei Tests mit meiner 'Referenz-Funktion' mit der eine relativ große Stringlist (90000 - 174000 Zeilen) in einem Richedit angezeigt wird, zeigte sich eine geradezu groteske Ausführungszeit von bis zu 16(!) sec. (siehe Anhang).
Delphi-Quellcode:
// stopwatch: System.Diagnostics.TStopwatch

Procedure StartStopWatch;
begin
  Stopwatch.Reset;
  Stopwatch.Start;
end;

Function Stoptime:double;
begin
  Stopwatch.stop;
  result:= Stopwatch.ElapsedMilliseconds / MSecsPerSec / SecsPerDay;
end;

procedure TGL4Mainform.XMLContent1Click(Sender: TObject);
  var stop: double;
      SL:TStringlist;
      FN: string;
begin
  FN:= 'filename.txt';
  SL:= TStringlist.Create;
  try
    If GetXMLContent(SL) Then
    begin
      SL.SaveToFile(FN,TEncoding.unicode);
      startstopwatch;
      richedit1.Text:= SL.Text;
      //richedit1.lines.LoadFromFile(fn);
      stop:= stoptime;
      richedit1.setfocus;
      richedit1.Lines.Add(#13#10'Anzeige der Daten im Richedit: ' + timestring(-stop));
      richedit1.Lines.Add(#13#10'Anzahl der Zeilen: ' + richedit1.Lines.Count.ToString);
    end;
  finally
    SL.Free;
  end;
end;
Mit einer mit Delphi 10.4.2 compilierten Version meines Programms dauert das ganze weniger als 2 Sekunden. Auf einem weniger betagten Rechner dürfte natürlich alles noch deutlich schneller gehen, aber bemerkenswert ist vor allem das Verhältnis. Das 'neue' TRichedit-Steuerelement ist demnach bis zu 8mal langsamer als das alte, und das gerade bei der kleineren XML. Die stammt allerdings von einem Mac und enthält z.T. alternative, aber gültige utf-8 Codierungen.
Wenn ich anstelle des TRichedit ein TMemo verwende, dauert derselbe Vorgang übrigens weniger als 100 ms (s. Anhang).
Delphi-Quellcode:
procedure TGL4Mainform.XMLContent2Click(Sender: TObject);
  var stop: double;
      SL:TStringlist;
      FN: string;
  const mask = 'content';
begin
  setmaincursor(crHourGlass);
  FN:= 'filename.txt';
  SL:= TStringlist.Create;
  try
    If GetXMLContent(SL) Then
    begin
      SL.SaveToFile(FN,TEncoding.unicode);
      startstopwatch;
      memo1.Text:= SL.Text;
      stop:= stoptime;
      memo1.setfocus;
      Memo1.Lines.Add(#13#10'Anzeige der Daten im Memo: ' + timestring(-stop));
      Memo1.Lines.Add(#13#10'Anzahl der Zeilen: ' + memo1.Lines.Count.ToString);
    end;
    SetMainCursor(crDefault);
  finally
    SL.Free;
  end;
end;
Aber einige optische Gimmicks wie mehrfarbiger Text sind eben mit einem TMemo nicht zu realisieren. Auch TListbox fällt als Alternative aus, da es mit so großen Listen offenbar nicht umgehen kann.
Als Workaround hatte ich die Stringlist in einer Datei zwischengespeichert und anschließend in das Richedit geladen. Das dauert zwar nur gut 2 sec, aber leider werden dann nicht alle Sonderzeichen korrekt dargestellt. Eine Speicherung als utf-8 (TEncoding.UTF8) schlägt fehl ('Keine Zuordnung für Unicode-Zeichen in der Multibyte-Zielcodeseite vorhanden'), und bei Speicherung als 'Unicode' (TEncoding.Unicode) dauert der Ladevorgang ebenfalls >15 sec, dafür ist das Ergebnis wenigstens korrekt.
Also eine absolut unbefiedigende Situation. Oder gibt's noch irgendeine Stellschraube bei TRichedit, die ich bisher übersehen habe? Oder einen brauchbaren Workaround?

Gruß LP
Miniaturansicht angehängter Grafiken
memo-export.jpg   richeditexport.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#2

AW: Desaströse Performance von TRichedit

  Alt 11. Sep 2024, 15:34
Kannst du deinen Test zur Verfügung stellen damit man das nachvollziehen kann. Eine mögliche Ursache könnte die Verwendung einer neueren Windows DLL für das RichEdit sein. Deswegen wäre es hilfreich, den für die Verzögerung relevanten Part zu finden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
347 Beiträge
 
#3

AW: Desaströse Performance von TRichedit

  Alt 11. Sep 2024, 16:28
Hi,

TRichView is very specific class, is not one of the usual Windows basic classes, yet it is encapsulated as one, it comes with own COM connection and interfaces even if you didn't ask for them,

However, there is few versions and they differ a little bit, you can get better knowledge of what version you can use from here:
https://learn.microsoft.com/en-us/wi...-edit-controls

Now to what i think is happening with your case, and as i don't have any newer than XE8, so my thoughts here are more general and very wide, so sorry if i didn't hit anything helpful:
1) XE8 do use RICHEDIT20W , this is version 2.0 and somehow it is fast enough very close to Windows WordPad, so it will be nice to share with us the difference between the versions you witnessed the performance degradation.
2) The problem with such classes are messages, the more you introduce the more functionality you can have, yet some of these message will affect the performance greatly as they will be used by the OS in very callback style on each line !! this will as you called it will be catastrophic performance drain, to explain this more, imagine you have a TListView with mixed design, wrongly performing like virtual and non virtual, in this case for each line you add there will a message handle even you already sent the caption and items and ...etc, yet messages will be delivered and must answered, again in wrongly mixed design these message will answered with nothing by the default handler and yet visually it will be alright but the speed will suffer greatly, this might be happening with RichView classes, specially if there is custom background handling.

In all cases,
1) try to find the class (version) you see performance degradation.
2) If you can access the sources then compare and share with us what messages implemented for the old and the new one, the procedures will looks like this
procedure XXXXX(var Message: TMessage); message YYYYY; .


In case these helps and shows something useful, then you have to strip the code and remove the messages and most likely will see a great deal of performance boosting, of course you will loose some functionality, but if you do not care about stuff like bidiMode which of course can't affect the speed, but others like WM_PAINT and its sisters.

Hope that helps.
Kas
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
156 Beiträge
 
Delphi 12 Athens
 
#4

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 00:05
Kannst du deinen Test zur Verfügung stellen damit man das nachvollziehen kann.
Ich habe mal zwei Dateien angehängt, die ich jeweils aus der Stringlist mit MyStringlist.SaveToFile(Filename,TEncoding.unicode) gespeichert habe. "Windows_ITunesContent.txt" enthält Daten einer Itunes-Mediathek unter Windows 10, "MacOS_ItunesContent.txt" stammt von einer Itunes Mediathek unter irgendeinem MacOS (aus 2018). Wenn ich die an ein Richedit verfüttere, dann stellt sich das beschriebene Verhalten ein. Vielleicht hilft's ja weiter!

Gruß LP
Angehängte Dateien
Dateityp: zip TestDateien.zip (1,94 MB, 15x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#5

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 01:03
Ja, Delphi nutzt aktuell das Richedit 4.1 und davor ewig lang die 2.0.
Kann/wird gut sein, dass sich dabei hier und da bissl was geändert hat.


Erstmal solltet ihr einwas bedenken.
Delphi/Embarcadero pfusch dort bereits extrem pervers an der Komponente rum und verbiegt mehr schlecht als recht die Zeilenumbrüche.
-> SelStart/SelLength stimmen nicht mehr mit den Positionen im Text-String überein ... je Zeile verrutsch es um ein weiteres Zeichen.

Windows arbeitet hier mit #13 (erschreckender Weise) und Delphi bricht das halbherzig/teilweise auf #13#10 um.


Außerdem kapselt TRichEdit die Komponente des Betriebssystems
und da hat Microsoft scheinbar nicht vor zukünftig noch irgendwas groß dran machen zu wollen.

Die Referenzimplementation für TRichEdit (WordPad) soll angeblich abgeschafft werden
und die Referenzimplementation für TMemo (Notepad) wurde auch verunstaltet. (nutzt jetzt anstatt dem Multiline-EDIT des GDI ein 3D-gerendertes RichEditD2D des Direct2D)




Bei RichEdit.Text und RichEdit.Lines.Text/LoadFromFile (ebenfalls beim TMemo) muß man auch unterscheiden, dass .Text direkt via WM_SETTEXT ins Control geht,
während Lines (TStrings) per se Zeilenweise zugreift ... teilweise wird aber im TStrings-Nachfahren doch auf's WM_SETTEXT umgeleitet, anstatt wirklich jede Zeile einzeln (aber nicht bei allen Controls)

Beim Lines.Text wird aus allen Zeilen ein neuer String zusammengebaut (und das nicht wirklich sehr optimal)
beim LoadFromFile wird dazu auch normal erstmal alles als TBytes in den RAM geladen, das dann via TEncoding erstmal in einen String umgewandelt (normal das dann in viele Strings zerlegt und anschließend erneut wieder in "einen" string zusammengesetzt)

Also die Stringlist macht das so,
aber TRichEdit leitet Lines.Text nahezu direkt an EM_STREAMIN weiter (es jagt den Text nur noch sehr oft Stückchenweise durch ein TEncoding)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (12. Sep 2024 um 01:36 Uhr)
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
156 Beiträge
 
Delphi 12 Athens
 
#6

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 11:26
Ja, Delphi nutzt aktuell das Richedit 4.1 und davor ewig lang die 2.0.
Kann/wird gut sein, dass sich dabei hier und da bissl was geändert hat.
'Bissl' ist gut!
TRichEdit leitet Lines.Text nahezu direkt an EM_STREAMIN weiter (es jagt den Text nur noch sehr oft Stückchenweise durch ein TEncoding)
Gerade das scheint mir der Flaschenhals zu sein und erklärt auch, weshalb die Mac - Daten besonders Resourcenhungrig sind. MacOS codiert z. B. im Gegensatz zu Windows in Dateipfaden Umlaute, aber auch Zeichen mit Akzent als Kombination aus Basis - Zeichen (z. B. 'a') und nachfolgendem Diakritischen Zeichen (¨).
Aber ich frage mich natürlich, weshalb das in der früheren Version von TRichedit deutlich schneller ging, und erst recht im TMemo.

Gruß LP
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#7

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 12:20
Ich habe das mal hier mit Delphi 12.1 und einem VCL-Form, einem RichEdit, einem Button und einem Label drauf ausprobiert:
Delphi-Quellcode:
procedure TForm866.Button1Click(Sender: TObject);
begin
// var FN:= 'c:\Users\Uwe\Downloads\TestDateien\Windows_ITunesContent.txt';
  var FN:= 'c:\Users\Uwe\Downloads\TestDateien\MacOS_ItunesContent.txt';
  var sw := TStopwatch.StartNew;
  richedit1.lines.LoadFromFile(fn);
  label1.Caption := sw.ElapsedMilliseconds.ToString;
end;
Ohne Debugger dauert das bei der Windows-Datei gut 1 Sekunde und bei der MacOS-Datei knapp 4 Sekunden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
156 Beiträge
 
Delphi 12 Athens
 
#8

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 13:16
Ich habe das mal hier mit Delphi 12.1 und einem VCL-Form, einem RichEdit, einem Button und einem Label drauf ausprobiert:
Ohne Debugger dauert das bei der Windows-Datei gut 1 Sekunde und bei der MacOS-Datei knapp 4 Sekunden.
Das Verhältnis der Zeiten entspricht ja fast genau den von mir ermittelten Zeiten. Die enorme absolute Dauer ist wohl u.a. meinem in die Jahre gekommenen Rechner geschuldet. Aber auch mit meinem IT-Methusalem ging es ja mit der früheren Version (Delphi bzw.Trichedit) bedeutend schneller, ebenso wie aktuell mit TMemo.
Und 4 Sekunden sind heutzutage für eine Datei von gerade mal 6 MB auch ganz schön happig;
Festzustehen scheint, dass die aktuelle Implementierung von TRichedit gewissermaßen suboptimal ist.
Ich bin schon dabei, bei meinem Hauptprojekt überall dort, wo Performance eine Rolle spielt und Richedit-Features nicht unbedingt benötigt werden, das TRichedit durch ein TMemo zu ersetzen. So kommt wenigstens keine Langeweile auf

Gruß LP
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#9

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 13:37
Daten besonders Resourcenhungrig sind.
Bei TStringList.LoadFromFile hat man locker währenddessen über 3 bis 5 Mal so viel im RAM, wie die Datei groß ist. (plus noch 1 Mal, aber das ist nur der FileCache, welcher sich bei Überfüllung selbst entsorgt)
Es wird also normal mit Win32 schon ab durchschnittlich 500-700 MB zu Problemen kommen, da die ersten 1+1 bis 1+2 Mal jeweils als zusammenhängender Block im Speicher Platz finden müssen.

Man könnte theoretisch versuchen TCustomRichEdit.CreateParams zu überschreiben (TWinControl.CreateSubClass ist leider nicht virtuell) und dort auf die Version 2 umstellen (ich weiß aber nicht in wie weit die RichEdit-API nach unten kompatibel sind, aber Delphi hat ja eh nur einen Bruchteil der Möglichkeiten implementiert)

Alternativ eben manuell (NonVCL) via CreateWindow mit RICHEDIT_CLASSW (anstatt MSFTEDIT_CLASS) sich ein RichEdit erstellen.
Winapi.RichEdit.pas

k.A. ob es ein RichEdit von einem Frendanbieter gibt, welches nicht auf dem TRichEdit aufsetzt.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (12. Sep 2024 um 13:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.453 Beiträge
 
Delphi 12 Athens
 
#10

AW: Desaströse Performance von TRichedit

  Alt 12. Sep 2024, 14:24
Festzustehen scheint, dass die aktuelle Implementierung von TRichedit gewissermaßen suboptimal ist.
Ich habe das mal auf einen simplen WinApi-Aufruf reduziert und komme auf ziemlich dieselben Werte. Es hängt also wohl nicht an der Delphi-Implementierung.
Delphi-Quellcode:
  var FN:= 'c:\Users\Uwe\Downloads\TestDateien\Windows_ITunesContent.txt';
// var FN:= 'c:\Users\Uwe\Downloads\TestDateien\MacOS_ItunesContent.txt';
  var S := TFile.ReadAllText(FN, TEncoding.Unicode);
  var sw := TStopwatch.StartNew;
  RichEdit1.SetSelText(S);
  label1.Caption := sw.ElapsedMilliseconds.ToString;
Warum die doppelt so große Windows-Datei aber nur 1/4 der Zeit braucht erschließt sich mir noch nicht so ganz.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz