Performance-Analyse der neuen Datenstruktur "Map"

  • Doch es geht. Wenn man den Speicher nicht linear auf die benoetige Groesse erhoeht, sonder z.B. immer auf die naechste Zweierpotenz aufrundet hat man zwar minimalen Speicherverlust, reduziert aber die amortisierte Laufzeit beim Wachsen von quadratisch auf linear.

    Ich weiß - siehe >>Halbdynamisches Array<< ;)
    Der Performance-Vorteil besteht dann aber nur beim Hinzufügen ans Ende. Einfügen und Entfernen innerhalb sind weiter die Domäne einer Arraylist.

    Es ist auch keine Verbesserung von Redim, da dessen Funktionalität ja erhalten bleibt und bleiben soll. Verändert wird hingegen das Verhalten einer Funktion wie _ArrayAdd. Redim wird nicht angetastet.

    In C++ gibt es eine, die sich deque nennt und reserviert den Speicher in mehreren grossen Bloecken (meistens 4 kb). Die ganze Datenstruktur funktioniert wie ein Array, laesst sich aber wesentlich schneller fuellen.

    Standardisiert ist das bei der Deque meines Wissens nach nicht. Es kann auch vorkommen, dass die Deque als doppelt-verkettete Liste implementiert ist. Ich weiß aber nicht in welcher STL nun welche der beiden Implementierungen genommen wird.

    Edit: Jetzt weiß ich wieder wo ich die Deque als linked-list kenne: Python. Ob in C++ die Deque teilweise auch als linked-list implementiert wird weiß ich nicht.

    2 Mal editiert, zuletzt von AspirinJunkie (11. August 2014 um 12:42)

  • Wie ich bereits schrieb weiß ich nicht wie die Deque in der STL implementiert wird.
    Allgemein kann eine Deque sowohl als Array als auch als List implementiert werden und wird in anderen Sprachen ja auch so implementiert.
    Wenn es aber in der STL, wie du sagtest, auf konstanten Random-Access beschränkt wird ist eine Implementierung als List hingegen natürlich hinfällig.
    In C++ ist es demnach, wie du schon sagtest, also keine Liste.

  • Ich habe mir das ganze nochmal mit der aktuellen Beta angesehen (3.3.15.3).

    Dieses mal getrennt im Hinblick auf assoziative Arrays und sequentielle Arrays.

    Kurz zusammengefasst: Es gibt nicht DIE Datenstruktur die alle anderen outperformed, sondern es hängt viel mehr davon ab wieviele Elemente die Datenstruktur schlussendlich enthält.

    Zeitaufwand für das (einzelne hinzufügen) Erstellen eines assoziativen Arrays mit N Elementen:

    Zeitaufwand für das (einzelne hinzufügen) Erstellen eines sequentiellen Arrays mit N Elementen:

    Zeitaufwand für das (jedes einzeln) Auslesen aller Elemente eines assoziativen Arrays mit N Elementen:

    Zeitaufwand für das (jedes einzeln) Auslesen aller Elemente eines sequentiellen Arrays mit N Elementen:

    Testskripte und Diagramme als PDF liegen im Anhang.

    Edit: Assoziatives Array als 2D-Array mit binärer Suche hinzugefügt - interessantes Ergebnis da dies bei großen Datenmengen auch Map und Dictionary überholt.

  • Hi AspirinJunkie!

    Du hast dich in dieses Thema ja "damals" voll reingekniet. Respekt jedenfalls dafür!

    Hat sich seit dem bzgl. Geschwindigkeit/Ansprechverhalten/Usability etwas gravierend geändert?

    Assoziatives Array als 2D-Array mit binärer Suche hinzugefügt - interessantes Ergebnis da dies bei großen Datenmengen auch Map und Dictionary überholt.

    Ist das immer noch so?

  • So jetzt hab ich das ganze mal mit der neuen 3.3.16.0 durchlaufen lassen (auf einem anderen Rechner nun auf Win11).

    Hier die Ergebnisse (und im Anhang):

    Hat sich seit dem bzgl. Geschwindigkeit/Ansprechverhalten/Usability etwas gravierend geändert?

    Grundsätzlich: Nein - alles ist im relativen Verhältnis ziemlich gleich geblieben.

    Bei dieser Messung habe ich allerdings nicht die System.Collections-Objekte (Hashtable und SortedList) laden können - sonst wären die auch noch mit im Test gewesen - keine Ahnung was da los ist.

    Das die System.Collections.Hashtable nun aus dem Test herausgefallen ist, hat aber auch einen positiven Aspekt: Nun ist meine in purem AutoIt geschriebene Hashtable nun offiziell die schnellste Datenstruktur beim Lesen aus assoziativen Strukturen bei 1 Million Elementen! :D

    Ist das immer noch so?

    Das ist tatsächlich noch so - zumindest für Maps. Scripting.Dictionary bleibt bis 1 Million Elemente vorn.

    Das fürchterliche Verhalten von den AutoIt-Maps bei großen Elementanzahlen ist aber relativ leicht zu erklären:

    Wie ich in Erfahrung bringen konnte, hat das Hasharray der AutoIt-Map eine fixe Größe von 256 Elementen.

    Es findet zu keiner Zeit irgendein Resize statt! :rolleyes:

    Sprich: Bei vielen Elementen läuft man zwangsläufig in eine enorme Anzahl von Hashkollissionen und die dahinter stehenden Subelemente müssen linear durchsucht werden. Bei 1 Million Einträgen in der Map muss man hierdurch bei jedem Elementzugriff im Schnitt 2.000 Elemente eines Arrays linear durchlaufen!

    Da wird schnell klar warum dann selbst eine in purem AutoIt geschriebene Hashtable besser performt, da diese eben resized.

  • Zitat von Mars (aus der Shoutbox)

    AspirinJunkie: Ich kann die .zip in deinem Map-Thread nicht auspacken. Winrar und der Win10-FileExplorer sagen mir, dass das Archiv beschädigt ist :(

    Wenn ich die .zip aus #27 mit 7-Zip über das Kontextmenü (Explorer) -> 7-Zip -> Entpacken nach ... entpacke, dann erscheint folgende Warnung :

    (Version 7-Zip : 19.0 (x64) vom Februar 2019)

    Die Dateien sind aber vorhanden und die Dateigrößen stimmen !

    Mars : Ich habe die Dateien erneut gepackt (siehe Anhang). Funktioniert es bei Dir damit ?

  • Ich hatte auch erst anfangs Probleme mit dem Entpacken. Ich schaue per "Doppelklick" in die Zip-Datei, markiere dort die für mich interessanten Dateien, und kopiere sie in das von mir verwendete Verzeichnis.

    Das hat nicht funktioniert. Sehr seltsam...

    Was aber problemlos funktionierte war, die Dateien aus der Zip in das Downloadverzeichnis zu entpacken und von dort zu kopieren.

    AspirinJunkie

    Ich konnte die Ergebnisse von dir verifizieren, plus minus 10-20% in den Zeiten sehe ich bei diesen Laufzeiten der Scripte bei AutoIt einfach mal als "gleich" an^^

    Einzig die Datenbank/SQL-Scripte liefen bei mir ca. Faktor 30 schneller ab?!

    Welche Umgebung/Prozessor/Version nutzt du?

    Was als "Essenz" zu Maps eigentlich übrig bleibt, ist das es (wie so vieles andere in den "neumodischen" Programmiersprachen auch) überflüssig ist wie ein Kropf!

    Es gibt gegenüber den etablierten Methoden/Funktionen/Objekten Array und Dictionary(s) keinerlei Vorteile!

    Und so wie ich das sehe, weiß das Jos sehr wohl! Daher auch genau der "inoffizielle" Status in der aktuellen AutoIt-Version...

    Maps, kann man haben, muss man aber nicht!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    2 Mal editiert, zuletzt von Andy (20. März 2022 um 09:23)

  • Welche Umgebung/Prozessor/Version nutzt du?

    Ein Surface 4 Pro mit einem i5-6300U auf Win 11.

    Es gibt gegenüber den etablierten Methoden/Funktionen/Objekten Array und Dictionary(s) keinerlei Vorteile!

    Welche etablierten Dictionaries in AutoIt?
    Bisher hat man sich in AutoIt beholfen das externe VB-(glaube ich)-Dictionary zu importieren.
    In AutoIt selbst gab es bisher soetwas nicht.

    Und ein dynamisches Array wie es jetzt mit MapAppend gab es vorher auch nicht.
    Die klassischen ArrayList-Krücken wie meine Dynarray-UDF stinken Performancemäßig dagegen nicht an.
    Bis ca. 10.000 Elementen - und das wird der übliche Einsatz sein - ist es auch fixer als Scripting.Dictionary.

    Ich begrüße die Maps, da sie ein übersichtlicheres Coden bei höher Performance ermöglichen.
    Ich wüsste im Gegenzug nicht, warum ich gegen deren Einführung sein sollte, da ich keinen einzigen Nachteil erkennen kann den ich durch deren Einführung nun habe.

    Und so wie ich das sehe, weiß das Jos sehr wohl!

    Meintest du Jon?

    Einmal editiert, zuletzt von AspirinJunkie (20. März 2022 um 10:22)

  • Meintest du Jon?

    Ja.....das Alter, du weißt schon^^

    Bisher hat man sich in AutoIt beholfen das externe VB-(glaube ich)-Dictionary zu importieren.

    $oDictionary = ObjCreate("Scripting.Dictionary")

    Das meinte ich, was ist daran "extern"?

  • was ist daran "extern"?

    Es ist Teil des VBA-Frameworks. Also kein Bestandteil des resultierenden AutoIt-Codes selbst.

    Was das heißt habe ich Live hier an dem Code erlebt: Denn auf einmal funktioniert die System.Collections.Hashtable aus dem .Net-Framework bei mir nicht mehr, auf welche ebenso wie das Dictionary zugegriffen wird.

    Es ist ein externes Objekt und wenn sich dort was ändert kann sich das Verhalten deines Programmes ändern ohne, dass das Programm selbst geändert wird.

    Bislang lief es wunderbar und daher nutze ich es auch gerne.
    Aber ein integriertes ist definitiv die schönere Option (Siehe HashTable).

  • Dann grabe ich mal einen Thread wieder aus der 200+ Tage alt ist :D

    Beim herumbasteln ist mir etwas seltsames untergekommen, und zwar schien es mir so, dass Maps via Integer-Indexzugriff schneller sind als Arrays via Integer-Indexzugriff (hier wird also nur die reine Performance geprüft NACHDEM das Array / die Map vollständig initialisiert ist, also mit Daten gefüllt wurde, bzw. der Datentyp innerhalb feststeht). Also habe ich mehrere kleine Tests gebastelt die alle einen Geschwindigkeitsvorteil zwischen 5% und 20% ergeben haben, und ich frage mich ob ich da etwas falsch mache, oder ob das wirklich so ist.

    Anbei ist ein halbwegs repräsentatives Beispiel.

    - Gegeben ist eine Liste aus 1000 Vektoren der Länge LEN.

    - Normiere alle Vektoren dieser Liste.

    -> Vektoren kann man als Array[LEN], oder als Map der Länge LEN implementieren

    -> Die 1000 Vektoren Liste kann man auch als Array, oder als Map implementieren

    -> Die Funktion "Normalize" ist identisch und kann ohne Codeänderung für Arrays und Maps verwendet werden.

    -> Das Beispiel wurde gewählt, da es zeigt was ich meine ohne "zu theoretisch" zu sein. Der viele Overhead (es sind ja nicht "nur" Map/Array Operationen, sondern Schleifen, Calls, Locals, etc) drückt das Ergebnis etwas, aber dafür ist es "realistischer" als meine anderen Tests.

    Heraus kam, dass Maps (für diesen Anwendungsfall) zwischen 0% und 10% schneller sind als Arrays (je größer die Vektoren, desto schneller die Map). Kann das jemand reproduzieren, bzw. mit anderen Tests ergänzen/meinen Fehler finden? Falls man hier wirklich "einfach so" 10% rausholen kann indem man einfach die meisten Arrays in einem Skript durch Maps ersetzt, wäre das ziemlich praktisch. Dafür müsste man aber herausfinden "welche Operationen" auf Maps deutlich schneller sind (vielleicht sind es alle, vielleicht nicht? Zufälliger Indexzugriff etc. habe ich noch nicht getestet), und welche nicht. Bei Vektoren der Länge 3 ist der Unterschied quasi nonexistent (da macht der Overhead 80% der Laufzeit aus, daher sieht man hier nur sehr wenig), Vektoren der Länge 100 sind eher selten, das dient hier nur als Beispiel, weil man hier die vollen 10% sieht. Ein kleiner Bonus bei verschachtelten Maps ist, dass man darauf via $m[$i][$j] zugreifen kann (während man bei Arrays aufgeschmissen ist).

    lg

    M

  • Kann das jemand reproduzieren

    Kann ich - meine Ergebnisse deines Skriptes:

    Code
    Time needed to normalize 1000 vectors of length 30 in milliseconds
    Array:  28.07 (100%)
    Map:    26.90 (96%)

    bzw. mit anderen Tests ergänzen

    Ich habe mal die Vektorlänge ein bisschen erweitert und mal selbst das Testskript aufgebaut um nicht etwas zu übernehmen, was wir bisher vielleicht nicht sehen (Normalisierung.au3).
    Meine Ergebnisse:

    Code
             N       Norm(Map)     Norm(Array)
    ------------------------------------------
            10       0.012  ms       0.023  ms
           100       0.080  ms       0.080  ms
          1000       0.723  ms       0.781  ms
         10000      10.740  ms       8.033  ms

    Die Grundaussage Map ist schneller als Array lässt sich also erst einmal nur für kleine Vektorlängen halten.
    Aber auch da entspricht das ganze nicht den Erwartungen.
    Also sollten wir mal tiefer bohren und schauen an was das liegen könnte.

    Grundsätzlich unterscheiden sich die beiden Vektornormalisierungen ja nur durch den Elementzugriff und den Elementzuweisungen.
    Der Rest ist gleich, so dass wir diese Zeitenunterschiede dort wiederfinden müssten.

    Ich habe diese mal separat gemessen (Elementzugriff.au3 & Elementzuweisung.au3) und folgende Ergebnisse ermittelt:

    Wir sehen also, dass eine Map insbesondere bei den Zugriffszeiten bei geringer Größe mit dem Array mithalten kann und teilweise darunter liegt.
    Ab einer gewissen Größe jedoch wird es bösartig und die Zugriffszeiten für die Maps rauschen nach oben.
    Das war bisher auch schon bekannt und liegt - das ist meine Theorie hierzu - daran, dass die AutoIt-Map als statische Hashtabelle mit (ich glaube) 256 Einträgen implementiert wurde.
    D. h. darüber haben wir zwangsläufig Hash-Kollisionen die dazu führen, dass Elemente in den Sublisten linear durchlaufen werden müssen um auf Elemente zuzugreifen - das kostet unheimlich Zeit und spiegelt sich entsprechend in den Ergebnissen wieder.
    Eine dynamische Implementierung mit entsprechenden Resizes würde hier Abhilfe schaffen (Das Scripting.Dictionary hatte das Problem glaube ich nicht).

    Nun dennoch: Selbst die Ergebnisse bei kleinen Vektorgrößen sind mir nicht erklärbar.
    Ein Zugriff auf ein Array-Elemente sollte IMMER schneller sein.
    Intern ist das nur der (fast) direkte Zugriff auf eine Speicherstelle wo im Falle von AutoIt der Pointer zur dahinterliegenden Variable liegt - mehr nicht.
    Die Map hingegen berechnet erst aus dem Index einen Hash und mappt diesen auf den Indexraum der Hash-Tabelle.
    An diesem berechneten Index muss dann noch die Subliste für die Unterelemente linear durchlaufen werden und jeder einzelne Wert mit dem Key verglichen bevor man das gewünschte Element erhält.
    Kurz: Das kann NIE schneller sein.

    Da muss irgendein Schnitzer im AutoIt-Quellcode sein. Und der Fehler liegt nicht daran, dass die ihre Map so grandios schnell implementiert haben - nein die Array-Implementierung hat ein massives Problem.

    Ein kleiner Bonus bei verschachtelten Maps ist, dass man darauf via $m[$i][$j] zugreifen kann (während man bei Arrays aufgeschmissen ist).

    sicher? :/ : ($a[$i])[$j]

    Einmal editiert, zuletzt von AspirinJunkie (17. Januar 2023 um 08:01)

  • Mars , ich zitiere mich mal selbst aus diesem Thread:

    Ich konnte die Ergebnisse von dir verifizieren, plus minus 10-20% in den Zeiten sehe ich bei diesen Laufzeiten der Scripte bei AutoIt einfach mal als "gleich" an^^

    AutoIt ist ein Interpreter, die Ausführungsgeschwindigkeit von programminternen Vorgehensweisen ist also primär vom Skill des Programmierers/Developers und der von ihm verwendeten Werkzeuge/Funktionen/Frameworks des Interpreters abhängig, s. dazu auch Post #27, letzter Absatz!

    Natürlich hast du recht, wie AspirinJunkie übrigens auch.

    Die "Intention", einen Datenwert in einer (im Speicher stehenden) Liste über einen Index abzurufen, ist bei sämtlichen dieser Methoden gleich. Aus Prozessorsicht ist das, auch bei "verketteten" Listen, eine Sache von einer Handvoll Prozessortakte, also quasi nicht messbar!

    Ein interpretierter AutoItcode ist, und das weist du ziemlich gut :rock: , ca. 1000x langsamer bei Rechenfunktionen in (verschachtelten) Schleifen als entsprechender compilierter Code. Da spielen derart viele Faktoren in die Ausführungszeit rein...s. dein 2. Chart Mapzeit/Arrayzeit...die "Peaks" bei Vektorlänge 16 und 20 sind ggf. irgendwelche Festplattenzugriffe, schicken des Prozessors in den Stromsparmodus (ja, WÄHREND des Benchmarks^^) uswusf.

    Der Overhead beim Benchen muss dementsprechend so niedrig wie möglich gehalten werden, macht aber, und das ist ja einfach nachzuweisen, im vorliegenden Fall KEINEN Unterschied....

    Wenn es also wirklich auf Geschwindigkeit ankommt (und das meine ich nur im Bezug zu den auch hier im Forum von mir befürworteten Wettbewerben), dann MUSST du die schnellste Methode/Programmieridee verwenden: :P

    Das die System.Collections.Hashtable nun aus dem Test herausgefallen ist, hat aber auch einen positiven Aspekt: Nun ist meine in purem AutoIt geschriebene Hashtable nun offiziell die schnellste Datenstruktur beim Lesen aus assoziativen Strukturen bei 1 Million Elementen! :D

    WZBW!!! :party:

  • Ein Zugriff auf ein Array-Elemente sollte IMMER schneller sein.

    Genau das ist mein Problem als ich darüber gestolpert bin... Wie kann ein Hashtable schneller sein als... "a * x + b" (Pointer an die richtige Stelle schieben ist eine lineare Funktion). Das will sich mir nicht erschließen. Im alten au3 Code könnte ich mich mal durchgraben wie die Implementierung konkret aussieht (vermutlich "nicht" einfach einen Pointer verschieben, sondern irgendwelcher furchtbar komplizierter Kram), aber Lust habe ich darauf nicht :D

    (ja, WÄHREND des Benchmarks^^) uswusf.

    Der Prozessor weiß eben wie man Powernapping betreibt. Der legt sich für ne Mikrosekunde hin und arbeitet danach direkt weiter ^^

    sicher? :/ : ($a[$i])[$j]

    Da hab ich wieder nur den halben Text geschrieben, im Kopf war da irgendwo noch ein "ByRef" (das war genau mein Problem wofür ich ein Ticket geschrieben habe... Es gibt außer in Funktionsaufrufen keine Möglichkeit ByRef auf verschachtelte Arrays zuzugreifen).

    Beispiel:

    Code
    Local $m[], $m2[]
    $m[0] = $m2
    
    $m[0][1] = '[0][1]' ; <- ByRef Zugriff auf die verschachtelte Map
    $m[0][5] = '[0][5]' ; <-
    ConsoleWrite($m[0][1] & ' ' & $m[0][5] & @CRLF)


    Edit:

    Noch ein Test: $Array[Func()] ruft Func() immer 2x auf. Das wurde schon vor Ewigkeiten entdeckt. Die Devs haben dazu damals gesagt, dass das eben so ist weil es intern aus irgendwelchen Gründen so gemacht wird. Requests in die Richtung wurden abgelehnt. (Das schreibe ich gerade aus dem Gedächtnis, Links etc und konkrete Quellen habe ich keine parat).

    Interessanterweise ruft $Map[Func()] die Funktion aber nur 1x auf. Vielleicht liegt hier der Hase im Pfeffer? Wenn grundsätzlich Ausdrücke im Mapindex nur 1x ausgeführt werden, während es bei Arrays immer 2x ist, dann könnte das einiges erklären. Auch ein $Array[$i] hat vermutlich zwei Evaluationen von $i (ich kann nicht genau sagen, ob das doppelte Evaluieren "immer", oder nur für Funktionen passiert, da ich ja nicht überprüfen kann, ob $i 2x evaluiert wurde ohne eine Funktion zu verwenden die einen Zähler hochzählt oder einen Konsolenoutput hat), ein $Map[$i] hingegen (vermutlich) nur eine.


    Edit2:

    Noch mehr Tests: Scheinbar ist dieses Verhalten (doppeltes Evaluieren) inkonsistent. Das heißt "manchmal" wird es gemacht, und "manchmal" nicht...

    Das Erwartete Ergebnis im folgenden Code ist, dass Array[Array[Func()]] insgesamt 4x Func() aufruft. Es sind aber trotzdem nur 2x. Es zeigt sich, dass das innere $Array[Func()] nur 1x evaluiert, das äußere aber 2x (weshalb das innere 2x und nicht 4x evaluiert wird). Ich werde noch wahnsinnig... :/

    Edit3:

    Für Arrays gilt: Lesender Zugriff -> Index wird 1x evaluiert, Schreibender Zugriff -> Index wird 2x evaluiert (glaube ich).

    Edit4:

    Allerdings erklärt das nicht warum Maps beim lesenden Zugriff (in meinen Tests) ebenfalls schneller waren, obwohl Arrays hier keine Rechenzeit verschwenden.

    Genug Edits für heute...

    lg

    M

  • Die Devs haben dazu damals gesagt, dass das eben so ist weil es intern aus irgendwelchen Gründen so gemacht wird.

    Naja, dann ist das eben so^^....genau wie das kopieren von (Text-) Variableninhalten bei sämtlichen "internen" Funktionen. Leg mal einen mehrere hundert MB großen Text an und lass auf diesen dann die durchaus schnellen Text/Stringfunktionen los und beobachte die Speicherauslastung....dabei hatte ich festgestellt, dass die Ausführungsgeschwindigkeit der Funktionen teilweise höher ist als die Zeit, den Speicherbereich zu kopieren...auch so kann man ein Programm "verlangsamen" 8o

    Was logisch erscheint, sind doch die "blauen" aka internen Funktionen nichts weiter als gewrapperte C(++)-Funktionen aus den standardisierten Bibliotheken. Da erfindet niemand das Rad neu! Die Laufzeit "innerhalb" der Funktion ist also identisch mit der eines kompilierten Programms!

    Was die Zeit frisst, ist der "selbstgestrickte" Overhead. Und mit Sicherheit die Art und Weise der Programmierung. Ja, was mir schon vor beinahe 40 Jahren Ärger mit HP einbrachte, als ich denen als "dummer" Maschinenbaustudent einen Auftrag von mehreren hunderttausend DM versaute, weil ich einen Grafiktreiber eines CAD-Systems (damals ME30) umgeschrieben und so um mehrere Faktoren beschleunigt hatte. So bestand für die Hochschule auch kein Grund, die "neuen" (und schnelleren) Systeme zu kaufen. Damals war ich noch stolz darauf, bis ich bei der folgenden CBIT hochkant vom HP-Messestand flog, mit Geleitschutz wie ein Schwerverbrecher....

    Was musste ich auch die Schnauze aufreißen und sagen, dass ein langsames und "schlechtes" Programm auch nicht schneller und besser wird, wenn man es durch einen "neuen" C-Compiler jagt....Es führt den "schlechten" Code nur schneller aus^^

    Für Arrays gilt: Lesender Zugriff -> Index wird 1x evaluiert, Schreibender Zugriff -> Index wird 2x evaluiert (glaube ich).

    Wenn dann noch, wie bei den Strings, die Variablen aka der komplette Array-Speicherbereich vor jeder Operation kopiert werden, dann braucht man sich nicht wundern...ByRef ftw!

  • genau wie das kopieren von (Text-) Variableninhalten bei sämtlichen "internen" Funktionen. Leg mal einen mehrere hundert MB großen Text an und lass auf diesen dann die durchaus schnellen Text/Stringfunktionen los und beobachte die Speicherauslastung

    Das hatte ich mal bei StringRegExp beobachtet und dabei festgestellt, dass das bei den normalen Stringfunktionen wie z.B. StringMid etc. eben dort nicht auftritt.

    Ich hatte dann ein >>Ticket<< dazu eröffnet und das war ratz fatz behoben und (ich glaube) nur ein paar Wochen später in der nächsten AutoIt-Version übernommen worden.
    Seitdem habe ich so ein Verhalten nicht mehr feststellen können.
    Hast du da evtl. ein konkretes Beispiel dazu?

    Mars

    Du bist da etwas auf der Spur.
    Die doppelte Ausführung könnte wirklich mit dem Phänomen zusammenhängen. Zumindestens sagt dies uns, dass die Array-Implementierung ziemlicher Bullshit in AutoIt ist.

    Übrigens: Für das doppelte Ausführen bei Arrays hat jpm seit 2 Jahren einen Fix fertig, welcher aber bislang von Jon noch nicht eingespielt wurde.

  • Sorry an AspirinJunkie , wenn wir hier etwas OT gehen.

    Das Erwartete Ergebnis im folgenden Code ist, dass Array[Array[Func()]] insgesamt 4x Func() aufruft. Es sind aber trotzdem nur 2x. Es zeigt sich, dass das innere $Array[Func()] nur 1x evaluiert,

    Ich vermute mal so, anhand deines Bsp. Array[Array[Func()]] :

    Der Ausdruck zur Definition des Index wird immer 2-mal ausgeführt. Mit der Einschränkung der Auflösung von Innen nach Aussen.

    Wurde der innere Ausdruck [Func()] bereits aufgelöst, erfolgt das beim zweiten Aufruf nicht mehr. Dann wird nur noch der äußere Lesezugriff Array[Resultat_2.ter_Aufruf_Func] ausgeführt. Und das Lesen verweist dann beim 1.ten und auch beim 2.ten mal auf den selben Wert, sodass wir keinen Mehrfachzugriff registrieren.

    Ist aber nur eine Vermutung - in die inneren Abläufe können wir ja leider nicht reinschauen.

    Ich hab das mal nachgestellt, und das erklärt dann auch, warum in AutoIt keine Index-Generator-Funktion implementiert wurde. :P

    Spoiler anzeigen

    EDIT:

    schräger Hack für Index-Generator