FileFindFirstFile - schnellere Alternative?

  • Hallio zusammen,

    Ich brauche fleißig den FileFindFirstFile (und -NextFile) Befehl.
    Er ist in AutoIt auch RELATIV schnell. (Ich benutze ihn Iterativ nicht Rekursiv, weil er dann bei mir ein wenig schneller ist.) Aber um noch ein bisschen Geschwindigkeit vor allem in Netzwerken herauszuholen, wollte ich nach Alternativen suchen. Die sollen quasi nur einen Befehl übers Netztwerk absenden und dann bekomme ich gleich nicht nur die nächste Datei, sondern die ganze Dateiliste von diesem Verzeichnis. Natürlich ohne Unterordner, aber vielleicht gleich mit dem jeweiligen Änderungsdatum der Dateien!!

    Dazu habe ich hier einen Ansatzpunkt einer Lösung gefunden. Aber kann man das in AutoIt überhaupt umsetzen??

    Veronesi

    Einmal editiert, zuletzt von veronesi (9. Mai 2011 um 10:02)

  • Ganz ehrlich
    was willst du mit sowas, jemanden Auspionieren wat er auf der Platte hat ?

    schneller gehts nicht ausser auf SSD.

    Spoiler anzeigen
    [autoit]

    #include-once
    #include <array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    func drive_search_folder($pf)
    If StringRight($pf,1) <> "\" Then $pf=$pf&"\"
    local $serach_array[1],$x=1

    [/autoit] [autoit][/autoit] [autoit]

    $serach_array[0]=UBound($serach_array)
    _ArrayAdd($serach_array,$pf)
    $first=FileFindFirstFile($pf&"*.")
    If $first = -1 Then
    $while=0
    Else
    $while = 1
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    While $while
    $next=FileFindNextFile($first)
    If not @error Then
    $serach_array[0]=UBound($serach_array)
    _ArrayAdd($serach_array,$serach_array[$x]&$next&"\")
    Else
    $x=$x+1
    If $x > $serach_array[0] Then ExitLoop
    FileClose($first)
    $first=FileFindFirstFile($serach_array[$x]&"*.")
    If $first= -1 Then ContinueLoop
    EndIf
    WEnd
    FileClose($first)
    _ArraySort($serach_array, 0, 1, 0, 0)
    Return $serach_array
    EndFunc
    ;---------------------------------------------------
    Func drive_search_file($pf,$type)
    Local $file_output[1],$x=0
    $file_output[0]=0
    $folder=drive_search_folder($pf)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $x=$x+1
    If $x > $folder[0] Then ExitLoop
    $first=FileFindFirstFile($folder[$x]&$type)
    If $first = -1 Then ContinueLoop

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    $next=FileFindNextFile($first)
    If Not @error then
    $file_output[0]=UBound($file_output)
    _ArrayAdd($file_output,$folder[$x]&$next)
    Else
    FileClose($first)
    ExitLoop
    EndIf
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    WEnd
    Return $file_output
    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von Rodny_le_lude (9. Mai 2011 um 09:22)

  • Ich will nichts ausspionieren!!!
    Ich muss lediglich Daten zwischen verschiedenen Laufwerken synchronisieren. (Sind übrigens alles SSD!!!)

    Und Robocopy ist zu langsam.
    Meine Lösung basiert auf FileFindFirstFile, aber speichert nicht in einem Array, da das Durchsuchen des Arrays auf Unterschiede zu lange dauert. (Entweder mit _ArraySearch oder _ArraySort und dann _ArayBinarySearch => Beide zu langsam)

    Ich nutze dazu Scripting.Dictionary. Das ist beim Durchsuchen massiv schneller!

    Damit wir uns richtig verstehen: Meine Lösung funktioniert gut. Und ist auf langsamen Netzwerken (übers Internet) etwa 4x schneller als Robocopy. Einfach in einem Gigabit Netzwerk ist es nur wenig schneller (wenn überhaupt) als Robocopy!
    Deshalb wollte ich für FileFindFirstFile evtl. eine schnellere Alternative wie im beschriebenen Link!

  • Du bist dir aber im klaren das AS eine Scriptsprache ist u. das es nicht möglich ist Daten schneller auszulesen als es die
    Spezifikation der HardDrive zulässt. Oder verstehe ich dich komplett Falsch.
    Oder brauchst du eine optimierte Synchronisation der einzelnen Datenbestände\Auflistungen (Echtzeit) mit verzögerung :D

    wir sprechen hier natürlich von petabyte

    4 Mal editiert, zuletzt von Rodny_le_lude (9. Mai 2011 um 09:52)

  • Ja, mir ist klar, dass AutoIt langsamer als C++ ist!
    Und dass irgendwo eine technische Grenze ist (HDD) ist auch klar!
    Ich wollte einfach das Maximum bei der Synchronisierung herausholen.

    Deshalb habe ich mir auch mal kurz C++ angeschaut. Aber das scheint mir komplizierter zu sein......
    Und als ich eben den Link gesehen habe, und gelesen habe, dass er von 30 Sekunden auf 2-3 Sekunden heruntergekommen ist, tönte das für mich interessant! Nicht mehr und nicht weniger.


    RSync kenne ich nicht. Lässt sich das ähnlich wie Robocopy in AutoIt einbinden, oder muss dann jeder eine Software installieren? (Das wäre dann ungünstig)

    Ehrlicherweise lässt sich wohl mit AutoIt nicht mehr viel rausholen.
    Wieviel schneller ist wohl FileFindFirstFile in C++?
    Oder ist AutoIt da schon (fast) so schnell wie es die HDD überhaupt zulässt?

  • Ach ja: es geht um 148GB Daten, welche jede Nacht übers Internet (!!!!) synchronisiert werden sollen.
    Internet Upspeed: 70MBit/s
    Internet Downspeed: 70MBit/s (synchrone Backbone Leitung)

  • Ok
    Und da C++ für mich zu kompliziert ist, lasse ich das wohl besser!
    Ist ja auch jetzt schon ca 4x schneller als Robocopy übers Internet!

    RSync schaue ich aber irgendwann noch mal an.
    Danke + Grüße
    Veronesi

  • Zitat

    Ach ja: es geht um 148GB Daten

    OMG das sind ca 20~30SEK mit meiner Function die ich dir oben gepostet habe, bricht davon die Welt zusammen.
    Also ungefähr 1 Minute um zu ermitteln ob Daten Ausgeglichen werden müssen zwischen zwei instanzen, danach beginnt der Download bzw Upload.
    Is doch Esay. :P

    EDIT:
    sind es immer gleiche DatenStrukturen also Dateien mit gleichem Namen die du Austauschen willst\musst??

    • Offizieller Beitrag

    Hi,
    wie groß ist denn der Unterschied am Tag? Ggf. ist die Ermittlung ja "teurer", als stumpfes kopieren.
    Sprich Vollversorgung anstatt Deltaversorgung.
    Bzgl. rsync und install guck mal hier. http://it-em.net/joomla/index.php?option=com_content&view=article&id=49&Itemid=54cms/front_content.php
    Sieht nicht danach aus.

    Mega

  • Ich hab's wohl falsch geschrieben!
    Es sind ca 148GB Daten die täglich ändern. (Viele Mitarbeiter...)
    Das gesamte Datenvolumen beträgt rund 4.1TB. Und diese 4.1TB müssen durchsucht werden. (ca 12'000'000 Dateien in ca 100'000 Ordnern)

    Dies ist ein kleineres Entwicklungslaufwerk mit einer Menge Delphi Source Code und Microcontroller Source Code und Exe Dateien von etwa 45 Softwareentwicklern.

    Mit meinem Script läuft das bis jetzt einwandfrei. Wollte es halt etwas verbessern.

  • Und ja: es sind WIRKLICH ca 148GB die pro Tag ändern!
    Wollte es erst auch nicht glauben, aber wir haben's mehrmals überprüft!

    Gut, es schwankt zwischen 60GB und 170GB / Tag

  • Also ich hab jetzt mal ein wenig gerechnet und die Übertragung von 150gb bei 70mbit dauert in etwa 5 Stunden. Wie lange dauert es denn bei dieser Datenmenge die Liste der zu kopierenden Dateien zu erstellen?
    Würde es evtl. einen zeitlichen Vorteil haben "live/nebenher" zu prüfen ob eine Datei übertragen werden soll oder nicht?

    Du könntest ja mit einem Übertragungsscript und einem Analyse Script arbeiten welche paralell laufen. Das Analyse Script startet etwas früher und übergibt an das Übertragungsscript in regelmässigen abständen eine Liste der zu übertragenden Dateien. Das Übertragungsscript kann dann bereits anfangen zu kopieren solange das Analysescript noch die Dateien ermittelt. Für eine bessere Auslastung wäre vielleicht sogar der Einsatz von multiplen Übertragungsscripten denkbar, die sich immer vom Analysescript neue Listen geben lassen.

  • Ja, die Übertragung wird wohl so ca. 5 Stunden dauern. Die Internetleitung hat vermutlich nur kleine Schwankungen, da es eine Businessleitung ist und somit garantiert Bandbreiten. Aber wenn zwischendurch ein Server "nicht so mag..."
    Ich weiss einfach, dass der gesamte Prozess (Überprüfen, was geändert werden muss und kopieren) ca. 7h 15 Minuten dauert.

    Das kann in etwa sein, da für das Scripting.Dictionary der Quelle (4.1TB Daten) etwas mehr als 1h benötigt wird.
    Für das Scripting.Dictionary des Ziels wird auch etwas mehr als 1h benötigt.
    Und dann ca. 5h kopieren! (= 7h Total)

    Da Quelle und Ziel auf unterschiedlichen Datenträgern (und Servern) liegen, könnte man Quelle und Ziel gleichzeitig einlesen. Aber ich kann die Daten nicht in ein Array einlesen, da AutoIt maximal 16Millionen Einträge pro Array erlaubt. Und die könnten vielleicht schon bald erreicht sein.
    Auch ist das Durchsuchen der Arrays (auch mit ArrayBinarySearch) langsamer als das durchsuchen von Scripting.Dictionary!

    Aber dazu habe ich zwei Threads offen:
    Performance mit Scripting.Dictionary und
    Objekte übergeben

    Damit ich den Performanceverlust des Scripting.Dictionary nicht habe, lese ich jeweils nur eine Verzeichnisebene der Quelle und des Ziels ein. Danach wird diese Ebene synchronisiert.
    Danach werden die Objektinhalte (Scripting.Dictionary) gelöscht und es geht in die nächste Ebene.

    Gruss Veronesi