![]() |
ListView Performance bei vielen Datensätzen (FMX)
Hi,
ich bin auf der Suche nach Ideen für eine "bessere" Lösung. Aktuell habe ich eine ListView, die liegt auf einer Form die erst beim öffnen erstellt wird. Also nicht nur Visible True gesetzt wird, sondern wirklich über ein Create erstellt wird und danach wieder mit caFree entfernt wird. Das sollte auch so bleiben, da diese Logik sich durch das gesamte Projekt zieht. Das als Info vorneweg :) Also ich lade aktuell in diese Listview beim on Show der Form die Daten Asyncron in die ListView (Ja, das geht weil ich Sie vorher auf visible=false setzte und ein Ladekreis drüber lege). Die Listview hat 4 Felder und erhält ca. 138.000 Einträge. Das geht in ca. 3 Sekunden. Es gibt nun 2 Sachen die mich "stören". 1.) Die 3 Sekunden :lol: wenn ihr also eine Idee habt wie man noch schneller Daten in eine ListView laden kann und darstellen kann, immer her damit :) 2.) Das Listview.visible := true setze ich am Schluss meines Ladethreads innerhalb eines TThread.Synchronize weil das dann die Änderung an der Form sichtbar macht. Dieser Vorgang dauert auch nochmal ca. 2 sekunden. Also bis die Listview gezeichnet ist. Habt ihre eine Idee, wie man da noch was rauskitzeln kann? Ich bin im FMX Umfeld unterwegs. vG PJM |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
aber das Items hat ja auch noch ein BeginUpdate und EndUpdate. Wie auch bei der VCL, würde ich hier noch mehr davon ausgehn, dass es grundsätzlich nicht threadsafe ist, aber ordentlich getrennt, sollte es dennoch halbwegs sicher sein. Warum will man überhaupt so viel da reinladen? Dynamisch nachladen oder via einem Filter nur so viel, wie der Mensch verkraftet. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Der Vorschlag von himitsu, die ListItems dynamisch zu laden, ist m.E. aber der einzige Weg, das wirklich schnell zu machen. Dann müsste man natürlich die Such- und Filterfunktionen neu basteln. Das sieht dann auch so aus, als wären alle Einträge im ListView enthalten; tatsächlich kennt das ListView aber nur die ListItems, die gerade sichtbar sind. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zusätzlich kann man ggf. auch noch die Ermittlung der Datensätze aus der SQL-Datenbank optimieren.
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Wenn die Datensätze aus einer SQL Datenbank kommen, dann kann man sie auch "per page" laden.
In dem man immer die nächsten 50 oder die vorherigen 50 fetched und das Fetch offset entsprechend mit verschiebt. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Außerdem liegt der Dataset bereits geöffnet auf meinem TDataModule. Habe also keinen Overhead für das Öffnen des Datasets. Die CalcFields sind aus, haben aber auch keinen Impact auf die Ladezeit (getestet). Ich gehe in einer EOF schleife durch. Könnte mal versuchen mit einer for schleife die RecNo zu setzen, vielleicht fallen dadurch noch ein paar Prüfungen die im Next durchgeführt werden weg. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Jetzt bin ich verwirrt. Liegt das Performance-Problem beim Einfügen der Daten in den ListView oder beim Auslesen der Daten aus der Datenbank?
(Ja, ich weiß, ich habe mich bisher nicht sinnvoll beteiligt, nur mitgelesen.) |
AW: ListView Performance bei vielen Datensätzen (FMX)
Ja, das wäre eine Untersuchung wert: wo ist das Bottleneck?
Laden aus der DB oder Einfügen in das Listview? Ich gehe auch davon aus, dass die where Begingung des Selects einen passenden Index in der DB nutzen kann? |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Was "lange" braucht ist
Delphi-Quellcode:
Diese Funktion braucht für 138902 Datensätze 2309 ms zum einfügen in die Listview. Das sind 60 Einträge pro ms. Deshalb "langsam" in Anführungszeichen.
while not Query.Eof do
begin lListViewItem := ListView.Items.Add; lListViewItem.Objects.FindObjectT<TListItemText>('Field1').Text := lField1.AsString; lListViewItem.Objects.FindObjectT<TListItemText>('Field2').Text := lField2.AsString; lListViewItem.Objects.FindObjectT<TListItemText>('Field3').Text := lField3.AsString; lListViewItem.Objects.FindObjectT<TListItemText>('Field4').Text := lField4.AsString; lListViewItem.Tag := Query.RecNo; Query.Next; end; Der 2. Aufruf der "Lange" dauert ist das Anzeigen der Listview, also das setzen von Listview.Visible = true. Das dauert 907 ms. Auch hier ist deshalb langsam in Anführungszeichen geschrieben. Nochmal zum Thema SQL. Die Query ist bereits geöffnet (Filter werden direkt nach der Anmeldung gesetzt und öffnen wird im Hintergrund durchgeführt) , also keine Möglichkeit hier sehr sicher keine Optimierung zu erreichen. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
1. Lesen aus der Query (in lokale Dummy-Veriablen) 2. Schreiben (von Dummy-Werten) in das Listview, so viele, wie die Query Einträge hat Danach weißt, du, wie hoch der Anteil der jeweiligen Funktionalität ist. Darauf basierend kann man dann nach weiterer Optimierung suchen. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Von dem FMX-Dingern hab ich keine Ahnung. Aber kann man sich die 4 Spalten nicht vorab irgendwie merken, statt sie bei jedem Datensatz mit FindObjectT... neu zu suchen?
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Wäre hier nicht ein TListView im "Virtualmode" sinnvoll?
![]() |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Laden der Daten in 3 unterschiedliche TArray<String> Variablen - 620 ms Laden des Arrays in die Listview mit "add" befehl - 1611 ms Umstellen auf Visible=true - 1140 ms Zusammen 3371 ms Am meisten "stören" tatsächlich die 1140 ms im Visible:=true teil, weil da auch die Ladeanimation hängt. :-/ |
AW: ListView Performance bei vielen Datensätzen (FMX)
Chat-GPT glaubt, dass es auch beim FMX-ListView einen VirtualMode gibt: ListView1.OnUpdateObjects
Wenn das stimmt (wie schon erwähnt, hab ich keine Ahnung von FMX), könnten 2 der 3 Prozesse extrem beschleunigt werden. Selbst das Visible:=true wäre dann extrem schnell. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Und dummerweise fällt mir auf Anhieb auch erstmal keine Lösung ein, weder für's Einügen noch für's sichtbar machen. Vermutlich müsste man jetzt mal nachsehen, was dieses Anhängen der Zeilen bzw. einfügen der Daten in eine Zeile eigentlich macht. Ich könnte mir vorstellen, dass der Hinweis auf den ständigen Lookup nach dem Namen von @Papaschlumpf73 durchaus seine Berechtigung hat. Wenn man das anders lösen könnte ... Aber da bin ich jetzt ziemlich raus, da meine Erfahrung mit FMX bisher auch eher homöopathisch ist. Ich frage mich allerdigs gerade, ob man die Animation nicht irgendwie doch im Hintergrund abspielen könnte. Unter Windows/VCL würde ich mir zutrauen das irgendwie hinzuhacken, aber unter FMX? Aber vielleicht gibt es ja gerade unter FMX sogar eine einfachere Möglichkeit dazu, nur kenne ich die nicht. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Okay, neuer Zwischenstand und neue Erkenntnisse.
Es gibt 2 Dinge die ich in der ListView noch optimieren kann, die dazu führen, dass die Zeit (zumindest die, die ich messen kann, näheres gleich) drastisch sinkt. Ich hatte als Einstellung für die Items die ListView auf dynamic appearance gestellt und Sie entsprechend angepasst. Hab mir jetzt überlegt, ich brauche nicht notwendigerweise 4 Felder, 2 tun es auch. Dadurch kann ich die Listview umstellen auf die Ansicht mit Detailbereich. Dadurch kann ich auf das Find verzichten und direkt das Text und Detail Property ansprechen. Das drückt die Zeit zum SChreiben auf ca. 500ms. Wenn ich das Allign der Listview auf "none" stelle, wird für das Visible eine glatte 0ms. (Danke an Alister Christie mit seinem aktuellsten youtube Video für die Idee :lol:) jetzt zu dem Punkt warum ich sage, die die ich messen kann. Ich habe mich mit der Stopuhr daneben gestellt. obwohl ich mit TStopWatch arbeite und mir die Messwerte in Summe unter 1 sec. ausspucken, braucht die Form doch ca. 4 Sekunden bis fertig geladen und angezeigt ist. Habt ihr eine Idee woran das liegen kann? Ich bin im OnShow Event schon durch wenn ich die Messergebnisse angezeigt bekomme.:pale: |
AW: ListView Performance bei vielen Datensätzen (FMX)
Vielleicht weis jemand wo ich noch schauen kann, bzw. optimieren kann.
Ich hab jetzt mal getestet wie sich die Form verhält, wenn sie einmal dargestellt wurde und dann einfach mit hide und show wieder angezeigt wird. Das Funktioniert top. Nur das erste Öffnen dauert weiterhin 3-4 Sekunden. Ich hab jetzt aber absolut keinen Plan mehr, wo ich ansetzen kann. Im OnShow Ereignis der Form steht gar nichts mehr drin. Die Form ist dann für 3-4 Sekunden weis, danach sehe ich die gefüllte Listview. Ich bin auch schon mal in die ListView in einige Ereignisse mit dem Debugger rein, aber die laufen alle ohne Verzögerung. Ich finde den Prozess, der hier verzögert einfach nicht :-( |
AW: ListView Performance bei vielen Datensätzen (FMX)
Gibts für die LIstView selbst oder eine der Spalten oder die Items noch irgendwo Align, AutoSize oder AutoIrgendwas?
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Hoi, gibts leider nicht :-(
Ich hab mich jetzt durch die FMX.Listview durchgewühlt. Die Aufrufzeit von ca. 3-4 sec verteilt sich ziemlich genau zu je 1/3 auf folgende Funktionen procedure TListViewBase.DrawListItems(const AbsOpacity: Single); procedure TAppearanceListView.ApplyStyle; procedure TListViewBase.ApplyStyle; Ich befürchte, dass es sich nicht lohnen wird hier weiter zu optimieren. Ich habe jetzt einen Workaround gemacht, der mir zwar nicht ganz schmeckt, aber den ich jetzt so nehmen werde. Das Anzeigen dauert nur beim ersten mal so lange. Die Form wird jetzt erzeugt und hat eine Meldung die Angezeigt wird "Anzeige wird vorbereitet". Diese form wird dann während der Lebenszeit der Anwendung nicht mehr gelöscht, sondern nur noch mit Hide ausgeblendet. Man muss also beim ersten mal öffnen die 3-4 Sekunden warten und im Anschluss ist es jedes mal direkt da. Wenn ich gar nicht drum herum komme, werde ich eine eigene Filterlogik implementieren die dann schon beim Aufruf greift. Besonders blöd an der Stelle finde ich, dass alles beim Anzeigen der Komponente passiert. Das läuft natürlich alles im Hauptthread und da kanns mir passieren, dass die Anwendung dann fliegt, wenns dem OS zu lange dauert. Ich habe aber nicht wirklich Möglichkeiten hier einzugreifen, ohne die DMX-ListView selbst anzupassen, oder mir irgendwie abzuleiten. Naja, trotzdem danke für euer Feedback und Input :thumb: |
AW: ListView Performance bei vielen Datensätzen (FMX)
Machst du ein Feature draus. Die Software merkt sich immer den letzten Filter und wenn es noch keinen gab, gibst du einen "Mustermann"-Filter oder was da sonst so passt vor.
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Kennst ja sicher die Kunden die dir auf "hier müssen sie einen Filter vorgeben" antworten mit, "aber woher weis ich denn nach was ich filtern kann". So in die Richtung geht das:roll: |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Das Anzeigen aller Daten in einer Liste mit 138.000 Einträgen, die der Kunde eh nicht in ihrer Gänze verarbeiten kann, zeugt in der Regel von einem Informationsdefizit, was der Kunde wie oft von der Liste wissen will.
Das ist natürlich stark von dem konkreten Anwendungsfall abhängig, aber mit etwas Recherche und ggf. dem Kunden bei der Arbeit über die Schulter gucken kann man schon so einiges herausfinden. Handelt es sich z.B. um über einen langen Zeitraum erfasste Einträge, sind eventuell nur die letzten Tage, Wochen oder Monate überwiegend im täglichen Gebrauch relevant. Dann wäre vielleicht ein entsprechender Filter als Default geeignet. Für ältere Einträge aus einem bestimmten Zeitraum muss der Kunde diesen eben angeben. Anderer Fall: Es handelte sich um eine Liste mit Adress- und Kontaktdaten. Dann wäre eine Eingabemaske mit bestimmten Suchkriterien die erste Wahl (Stichwort: ![]() Leider kann der Kunde diese Art von Anforderungen meistens nur schwer oder gar nicht kommunizieren. Auf eine Frage wie "Was brauchst du am häufigsten?" folgt oft die Angst, dass alles was darauf nicht genannt wird dann später auch nicht möglich ist. Da hilft dann halt nur Zusehen und Nachfragen. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
|
AW: ListView Performance bei vielen Datensätzen (FMX)
Nja, wenn noch kein Filter vorhanden, dann "alles" laden (mit Limit, damit nicht zuviel/langsam)
oder zu Beginn eben garnichts automatisch laden. (erst nach Eingabe/Enter) WHERE einem LIKE :Filter + '%' dann noch ein LIMIT 100 (oder so) dran Wenn RecordCount = das Limit, dann noch ein Label/Hint anzeigen, dass eventuell nicht alles angezeigt wird und man vielleicht den Filter anpassen könnte, und/oder einen Knopf/Link "alles Laden", welcher das Limit erhöht, bzw. entfernt. (Label im AfterOpen/AfterRefresh des Query aktualisieren ... dort könnte man auch RecordCount und Limit mit anzeigen/erwähnen) Gibt es im FMX sowas wie ein ![]() |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Ich weis worauf die hinaus willst. Ja in FMX gibt es das TSKLabel das auch wie ein Link gestyled werden kann. Man kann auch einfach einen TSpeedbutton nehmen und ihm das passende StyleLookup verpassen. Werde mir das mal durch den Kopf gehen lassen. Danke schon mal für das ganz Feedback und den Input. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Der Vorteil an so Link-Labels istcja, dass man hier extrem frei ist.
Erstmal verschiedene Texte mit keinem, einem oder mehreren Links. Dann Skalierung, Schriftgrößen und auch Übersetzungen wesentlich einfacher, gegenüber mehreren zusammenhängenden Texten+Buttons. Klar, man könnte auch auch eine ComboBox, RadioButtons oder ein Popup nutzen, für Normal/Reset, Limit erhöhren, Limit noch höher, Limit aufheben und Dergleichen, oder man fügt solche Aktionen in den Fehler-/Hinweistext ein. |
AW: ListView Performance bei vielen Datensätzen (FMX)
Zitat:
Ich bezweifle, durch 183000 datensätze rollen notwendig ist. Das Filterproblem sollte im Query gelöst werden. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz