Große Datei durchsuchen - Optimierungsvorschläge gesucht

  • Ich bin noch bei der Durchsicht der von dir genannten Lua-Dateien und fange an, eine Verbindung zu erahnen. Das "goto definition" kriege ich dennoch nicht unter einen Hut damit. Das verwirrt mich. =O

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Es ging doch nur um das Verfahren, wie Begriffe (Definitionen) zu finden sind. Ob diese anschließend als CallTip oder zum Aufruf der Datei mit der Definition und Anzeige derselben verwendet wird, ist letztlich obsolet.

    Die Lua Dateien habe ich durchgesehen. Ich sehe da kein Rad, das schon erfunden wurde. :/ Bin ich blind? :/

    In den Lua Dateien ist gerade mal ein winziges Mini-Stückchen zur Erkennung, ob ein CallTip angezeigt werden soll, und das ist mit der Prüfung von "," und "(" schon erledigt. Meines Wissens, und nach dem, was ich mich vor Wochen im EN Forum mit Jos darüber unterhalten habe, gibt es in SciTE4AutoIt3 einen kompletten Lexer, der dahinter steht und einen Teil der Arbeit übernimmt, sowie weiteren komplexen Code wie die CallTip.cxx, die ich durchgearbeitet habe.

    Das alles gibts in PSPad nicht. Da gibt es keine LUA Schnittstelle, VBScript ist das Höchste, was PSPad bietet. Und damit ist noch nicht einmal eine Überwachung möglich, da es keine Timer gibt. ...

    Du brauchst also das Rad nicht neu erfinden. Die Funktion findest du in diversen Sprachen. ...

    Es ist vermutlich einfacher, wenn du diese funktionierenden Funktionen als Blaupause nimmst.

    Das suggeriert mir, es gäbe eine fertige Funktion, die CallTips aufbereiten und anzeigen kann. Das kann ich aber nirgends finden. Wenn ich auf dem Schlauch stehe, wäre ich froh, wenn du mir sagst, wie ich dieses "Rad" benutzen kann. Ich selbst bin nicht in der Lage, das zu finden. Und ich suche schon seit Monaten!

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • 87736-scite-calltip-example-1-png

    Hi Professor Bernd !

    (nur noch mal zu Sicherheit)

    Falls ich Dich richtig verstehe, dann möchtest Du nach Funktionsname ( den zugehörigen Text aus der au3.api als Tooltip anzeigen lassen.

    Möchtest Du auch die farbliche Hervorhebung des jeweilgen Parameters umsetzen ?

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

    • Offizieller Beitrag

    Also, die Anwendung von GoToDefinition findest du dann z.B. in "AutoIt Tools.lua" in der Funktion "AutoItTools:OpenInclude".

    Die Suche ist hier ganz simpel geregelt: Übergabe Suchbegriff (von Cursorposition) mit Name der Datei, wo zu suchen ist an die Funktion. In Lus ist das mit einer Regex-ähnlichen Suche gelöst.

  • Falls ich Dich richtig verstehe, dann möchtest Du nach Funktionsname (den zugehörigen Text aus der au3.api als Tooltip anzeigen lassen.

    Das ist richtig. Der User schreibt Funktionsname ( und drückt einen bestimmten Shortcut. Daraufhin wird ihm ein kleines Fensterchen (der CallTip) angezeigt, das aus zwei Zeilen besteht: Eine für die Syntax, die andere für die Beschreibung der jeweiligen Funktion. (siehe Screenshot) Der zugehörige Text wird aus der au3.api gelesen.

    Möchtest Du auch die farbliche Hervorhebung des jeweilgen Parameters umsetzen ?

    Auch richtig. 8o

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Also, die Anwendung von GoToDefinition findest du dann z.B. in "AutoIt Tools.lua" in der Funktion "AutoItTools:OpenInclude".

    Hallo BugFix, es tut mir leid, aber ich raff das nicht. Ich will doch keine Definition einer Funktion im Editor öffnen, sondern ein schwebendes Fenster über dem Editor anzeigen, das die Syntax und die Beschreibung einer Funktion anzeigt. Dabei darf das schwebende Fenster den Fokus nicht vom Editor wegnehmen, sodass man das Fenster sehen und gleichzeitig im Editor schreiben kann.

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Musashi

    Vielen Dank für die Infos und den Code-Schnipsel in Posting #15! :rock: In dem Trubel ist das untergegangen, aber ich hab es nicht vergessen. Im Gegenteil, ich arbeite bereits daran, die beiden Möglichkeiten mit einander zu verbinden: Arrays für die Funktions-Sets (= aufgeteilte Zeilen) und Dictionary für die Suche. Hat jemand eine Idee dazu?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    2 Mal editiert, zuletzt von Professor Bernd (16. März 2020 um 16:13)

  • Hier mein Code, der die Suche nach einem FuncName mithilfe von _ArrayFindAll durchführt. Verbesserungsvorschläge willkommen.

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Dictionary

    Wie könnte man denn mehrere Treffer (z. B. 30 für "Opt") mit einem Dictionary handhaben?

    Meine Idee war, dass man die Treffer (= Zeilen) sammelt und als 1 Element ("Opt") im Dictionary speichert. Dabei könnte man @CRLF als Trennzeichen mitspeichern. Nach der Suche erfolgt die Auswertung der Treffer. Dabei könnte man mit dem Trennzeichen die Treffer wieder auseinander splitten.

    Leider ergäbe das wahrscheinlich Probleme mit der Länge in 1 Element des Dictionarys, oder? In der api.au3 kann eine Zeile gerne mal 400, oder sogar 600 Zeichen lang sein. Wenn z. B. zum FuncName "Opt" 30 Zeilen gefunden werden, jede im Durchschnitt mit 340 Zeichen, ergäben zusammen über 10.000 Zeichen. Geht das überhaupt? Wie ist denn die Max-Länge eines Strings in einem Dictionary?

    Eine andere Idee ist, statt die Treffer-Zeilen direkt im Dictionary zu speichern, nur die Indexe (Indizes) zu speichern. Dann bei der Auswertung (nach der Suche) einen Zwischenschritt einbauen, mit dem die Indexe in Treffer (mit Zeileninhalten) konvertiert werden.

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Wie ist denn die Max-Länge eines Strings in einem Dictionary?

    Soweit ich es auf die Schnelle finden konnte, hat das Dictionary-Objekt keine implizite Obergrenze und wird nur durch den zur Verfügung stehenden Speicherplatz begrenzt.

    Die Eigenschaft .count (also die Anzahl der Schlüssel/Element-Paare in einem Dictionary -Objekt) ist vom Typ Long(Integer), also 32 Bit - das sollte mehr als ausreichen;).

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Ich habe fertig! (Den Code, um in einem Dictionary mehrere Treffer zu einem Suchbegriff zu speichern.)

    Geschwindigkeitsvergleich                                                                                                
    _ArrayFindAllTime: 0.0148594000
    DictionaryTime: 0.0000195000


    Ich danke allen hier im Thread für Tipps und Vorschläge, und vorallem chesstiger und Musashi für die Code-Schnipsel zu Dictionarys! :thumbup:

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Warum hast du Mars Ansatz nicht groß weiter verfolgt?
    Eine binäre Suche geht ratz fatz und kann im Gegensatz zur Dictionary-Variante z.B. auch dann verwendet werden wenn nicht der vollständige Funktionsname vorliegt, sondern erst (z.B. beim Tippen) nur der Anfang.

    Für eine binäre Suche braucht man:

    • Daten welche mindestens ordinalskaliert sind (also Operationen größer und kleiner als sind hierauf möglich wenn man zwei solcher Werte vergleicht).
    • Die Daten müssen sortiert vorliegen (mit der selben größer/kleiner-Logik wie in der anschließenden Suche)

    Wenn man dies gewährleistet , ist es dann im Grunde eigentlich kein Hexenwerk.
    Ich habe in meiner >>Dynarray-UDF<< für diesen Fall mal eine Funktion geschrieben mit welcher man den Match und den Vergleich ganz einfach über eine eigene Funktion austauschen kann.
    Damit wird der endgültige Code dann ziemlich kompakt:

    Edit: Und wenn es nur 4000 Zeilen sind dann wäre das einfachste ja nur StringRegEx zu bemühen:

    AutoIt
    #include <Array.au3>
    
    $s_FilePath = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 1, -1)) & 'SciTe\api\au3.api'
    $_File = FileRead($s_FilePath)
    
    $s_SearchString = "GuiCtrl"
    
    $a_Results = StringRegExp($_File, '(?mi)^' & $s_SearchString & '.*', 3)
    _ArrayDisplay($a_Results)

    In meinem Fall dauert die Suche damit nur ca. 2 ms. Für einen Calltip mehr als ausreichend schnell denke ich.

    3 Mal editiert, zuletzt von AspirinJunkie (14. April 2020 um 15:15) aus folgendem Grund: RegEx-Pattern vereinfacht

  • Hallo AspirinJunkie.

    Warum habe ich den Ansatz der binären Suche nicht weiterverfolgt? Offen gesagt, weil es mir zu hoch ist. (Respekt für alle, die das handhaben können!)

    Es gibt ein paar Themen, die ich vermeide, wo immer es möglich ist. Wie viele schon wissen, gehören dazu die RegExp's. Oder auch um Zeichenkodierung mache ich einen großen Bogen, von ANSI, ASCII, über UTF-16BE bis UTF-32, mit und ohne "Bumm" (BOM).

    Neben ein paar weiteren Themen vermeide ich auch binäre Suche oder Vergleiche. In diesem Fall deshalb, weil mein Code von vielen Vorbedingungen abhängig ist, die ich nicht immer beeinflussen kann. Eine binäre Suche ist nach meiner Kenntnis ein fragiles Unterfangen. Es genügt schon eine fehlende Vorbedingung (ordinalskaliert, sortiert), und schon funktioniert sie nicht mehr. Auch weiß ich nicht, welchen Einfluß die Zeichenkodierung der Datei auf die Suche hat.

    Ich habe mir das Posting mit deiner _DynArray-UDF angesehen. Großen Respekt für deine Arbeit! Wenn ich dann noch dein Code-Snippet sehe, könnte ich glatt in Versuchung geraten, die binäre Suche in Erwägung zu ziehen. ;) Das sieht in der Tat sehr kompakt aus.

    ...

    Gerade habe ich die _DynArray-UDF heruntergeladen und dein Code-Snippet im Posting hier oben ausprobiert. Läuft sehr geschmeidig. :)

    Eine binäre Suche geht ratz fatz und kann im Gegensatz zur Dictionary-Variante z.B. auch dann verwendet werden wenn nicht der vollständige Funktionsname vorliegt, sondern erst (z.B. beim Tippen) nur der Anfang.

    Für die Verwendung in meinem CallTipViewer ist das Gegenteil gewollt: Nur eindeutige Suchbegriffe! Die Suchbegriffe sind ausschließlich vollständige Funktionsnamen, keine Teile.

    Dennoch freue ich mich sehr über deinen Tipp! Mir sind schon ein paar Ideen gekommen, wo ich das bestimmt gut brauchen kann. ... Aber im Moment ist erstmal der CallTipViewer dran. :)

    Danke für deinen Beitrag,

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Warum habe ich den Ansatz der binären Suche nicht weiterverfolgt? Offen gesagt, weil es mir zu hoch ist. :whistling: (Respekt für alle, die das handhaben können!)

    Das ist kein Problem, wenn die Suche auch auf schwächeren CPUs in einer akzeptablen Zeit funktioniert kannst du es ja auch so belassen. Es ist ja nicht so, als ob die Calltips in nächster Zeit explodieren werden.

    Die Ansätze für schnellere Suchen solltest du im Hinterkopf behalten, dazu musst du nicht unbedingt über Laufzeitklassen bescheid wissen aber immer was in der Tasche haben um performant suchen zu können.

    Der Tag wird kommen, an dem du eine schnelle Suche brauchen wirst.

  • Ich glaube das Dict ist ohnehin schneller (habe es nicht ausprobiert). Falls es intern mit einem Hashtable arbeitet sollte die Zugriffszeit nahe O(1) sein und viel mehr als das ist nicht drin (nur eine Vermutung) :)

    Ein Vorteil der ArrayBinSearch + Regex ist, dass man so z.B. auch Schreibfehler/TeilMatches gut abarbeiten kann (hier ist ein Hashtable aufgeschmissen, da ein Schreibfehler idr zu einem völlig unterschiedlichen Hashwert führt), da das hier aber nicht gebraucht wird ist es wahrscheinlich Wurst welche Variante du im Endeffekt verwendest. Aber die Methode ansich kannst du dir merken, villeicht braucht man sowas ja später mal ;)

    M

  • Mars Die gleichen Gedanken hatte ich auch.

    Geschwindigkeitsvergleich                                                                                               
    _ArrayFindAllTime: 0.0148594000
    StringRegExpTime: 0.0044309000
    _DynArray-UDFTime: 0.0005477000
    DictionaryTime: 0.0000195000

    Edit: StringRegExp hinzugefügt.

    Edit 2: Wert für _DynArray-UDF korrigiert.

    Bernd.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    2 Mal editiert, zuletzt von Professor Bernd (17. März 2020 um 14:08)