Multithread-Dateikopie

8

Wir haben ein Dienstprogramm, mit dem Sie Dateien an einen gemeinsam genutzten Netzwerkspeicherort hochladen (und andere Vorgänge für die Datei ausführen) können.
Die Dateigröße variiert in der Regel zwischen einigen MB und 500 MB.
Es wurde der Vorschlag gemacht, dass wir beim Hochladen der Dateien an den freigegebenen Speicherort möglicherweise Multithreading unterstützen sollten - dies ist nicht in Byte-Blöcken erforderlich -. Jeder Thread sollte eine Datei auswählen und versuchen, sie hochzuladen.

Ich bin mir nicht sicher, ob Multithreading solche E / A-Vorgänge beschleunigen kann. Ist meine Vermutung gültig?

Wenn wir diese Funktionalität tatsächlich erstellen müssen, habe ich mich gefragt, was ein guter Entwurfsansatz für die Copy File Engine wäre.
Wäre es sinnvoll, ein Tool wie Robocopy zu verwenden (ich habe gelesen, dass die neueren Versionen Multithreading unterstützen)?

Bearbeiten: Entschuldigung für die Verzögerung und das Fehlen einiger wichtiger Informationen.
Dieses Dienstprogramm wird mit C # (.Net 2.0) erstellt, und jedes zukünftige Update muss auch .Net verwenden (Framework-Version ist keine Einschränkung). Das Dienstprogramm ist auf den Computern der Benutzer installiert (ca. 20 alle unter WinXP). Die Zielfreigabe befindet sich auf dem Win2k3-Server.

Bearbeiten 2: haben beschlossen, einige Tests mit einer einfachen Anwendung durchzuführen, die den Datei-Upload über TPL implementiert. Nach dieser Analyse werden wir entscheiden, ob wir fortfahren oder nicht. Vielen Dank an alle für die erweiterte Hilfe.

NoviceProgrammer
quelle
1
Welche Programmiersprache? In C könnte ein idiomatischerer Ansatz darin bestehen, asynchrone E / A zu verwenden und eine selectSchleife anstelle von Threads zu verwenden. Dazu müssen Sie zwar "Ihren Code auf den Kopf stellen" (der Code zum Kopieren einer Datei ist keine einfache Folge von Befehlen mehr), Sie müssen sich jedoch nicht mehr um die Thread-Synchronisierung kümmern.
Joey Adams
Die wahrscheinlich einfachste vernünftige Lösung besteht darin, das Betriebssystem alles erledigen zu lassen : SHFileOperation(FO_COPY). Damit erhalten Sie alle Optimierungen, die die Mitarbeiter von Microsoft für angemessen hielten.
MSalters
Husten Robocopy Husten ... Sie könnten es mit so etwas wie Robomojo
James Snell

Antworten:

19

Das hängt davon ab, was der begrenzende Faktor ist, nicht wahr? Wenn der Engpass das Hilfsprogramm ist, beschleunigen Sie sicher die Ausführung von mehr als einer Kopie oder die Verwendung mehrerer Threads. Wenn das Netzwerk der begrenzende Faktor ist, hilft das Hinzufügen mehrerer Instanzen des Dienstprogramms nicht weiter, da Sie immer noch nicht mehr als X Bytes pro Sekunde bewegen können. Tatsächlich kann es weh tun, weil Sie den zusätzlichen Aufwand für eine zweite Kopie der App haben. Gleiches gilt für Disk-IO. Sie können nur so schnell kopieren, wie jeder Computer von der Festplatte lesen und auf die Festplatte schreiben kann. Wenn das bereits ausgereizt ist, hilft das Hinzufügen von Kopien nicht weiter.

Was Sie tun müssen, ist zu testen, um festzustellen, was der Engpass ist, und von dort aus zu gehen.

GroßmeisterB
quelle
11

Wie Multithreading nicht hilft:

Mehrere Threads, die gleichzeitig von der Festplatte des Clients lesen oder gleichzeitig Daten über das Netzwerk senden, helfen überhaupt nicht, da es höchstwahrscheinlich nur einen Kommunikationspfad zwischen dem Client und dem Server gibt. Der Client liest höchstwahrscheinlich Dateien von einer einzigen Festplatte ab -drive, und die Dateien werden höchstwahrscheinlich auf eine einzelne Festplatte auf dem Server geschrieben. (Selbst wenn der Server über RAID verfügt, wird dies einen gewissen Unterschied bewirken, jedoch nicht viel.) Im Gegenteil, wie bereits erwähnt, wird die Leistung wahrscheinlich beeinträchtigt, da zwischen den eingelesenen Dateien ständig gesucht wird parallel auf dem Client und ständige Suche zwischen den Dateien, die parallel auf dem Server geschrieben werden. Außerdem werden die Dateien möglicherweise stark fragmentiert auf dem Server gespeichert.

Wie Multithreading hilft:

Multithreading kann jedoch auf andere Weise hilfreich sein: Mit nur zwei Threads auf dem Client kann die Datei-E / A von der Netzwerk-E / A desynchronisiert werden. Dies bedeutet, dass der Client gleichzeitig einen Teil einer Datei übertragen kann, während er den nächsten Teil von seiner Festplatte liest. (Der Server ist bereits in der Lage, gleichzeitig einen Teil einer Datei auf die Festplatte zu schreiben, während der nächste Teil vom Netzwerk empfangen wird.) Dies wäre sehr wichtigBeschleunigen Sie den Übertragungsprozess, da der Client dazu neigt, entweder den Netzwerkkanal oder den Plattenkanal (je nachdem, welcher langsamer ist) gesättigt zu halten, anstatt zeitweise auf jeden einzelnen zuzugreifen. Ich würde vermuten, dass jedes spezialisierte Dienstprogramm zum Kopieren von Dateien intelligent genug sein sollte, um dies zu tun, aber ich kann mich irren. Wenn also "Robocopy" ankündigt, dass sie Multithread-Kopien erstellen, ist das in Ordnung.

EDIT: Ich habe das Bit korrigiert, das ich über RAID geschrieben habe.

EDIT: Ich habe das Bit bezüglich der Anforderung von zwei Threads auf dem Server korrigiert.

Ich denke, das Wichtigste hier (wie fast überall) ist die Messung . Sie haben keine Kontrolle darüber, wie diese Dienstprogramme funktionieren. Sie wissen also nur, ob Sie dies so schnell wie möglich tun, wenn Sie den Durchsatz messen, um festzustellen, ob er in der Nähe des angekündigten Durchsatzes Ihrer Festplatte oder Ihres Netzwerks liegt (je nachdem, welcher Wert kleiner ist) .)

Mike Nakis
quelle
Dies scheint eine großartige Idee zu sein, aber ich verstehe nicht, wie das Dienstprogramm zur Dateiübertragung dies tatsächlich tun kann, es sei denn, es verfügt über Remote-Ausführungsberechtigungen (oder das Übertragungsprotokoll unterstützt dies von Natur aus). Ich versuche, ein Dienstprogramm zu schreiben, mit dem eine gigantische Anzahl von Dateien regelmäßig von einem NAS übertragen werden kann, und ich muss wirklich Wege finden, um die Zeit zu verkürzen.
Asad Saeeduddin
Ihre Frage ist sehr scharfsinnig und weist auf eine Ungenauigkeit in meiner Antwort hin. Der Server sollte die Netzwerk-E / A bereits vom Festplattenzugriff desynchronisieren, da Server normalerweise so arbeiten: Sie führen in der Regel asynchrone E / A aus, anstatt für jeden Client einen separaten Thread zu erstellen, der jeweils nur eine Aufgabe ausführen kann. Sie sollten sich also nicht um den Server kümmern müssen, sondern nur um den Client. Ich werde meine Antwort umformulieren.
Mike Nakis
@Asad Bitte beachten Sie auch, dass mit "Server" in diesem Fall jeder Computer gemeint ist, der sich am empfangenden Ende der Übertragung befindet. Es muss kein Computer mit einer bestimmten Serverrolle sein.
Mike Nakis
9

Beim Kopieren vieler kleinerer Dateien kann Multithreading hilfreich sein, da die Datenübertragung häufig lückenhaft ist, während das Programm Verzeichnisse nach der nächsten Datei durchsucht, diese öffnet und die Daten abruft.

Multithreading hilft auch, wenn sowohl der Client als auch der Server über einen parallelen Datenspeicher wie RAID oder SSD verfügen: alles, was bei höheren Warteschlangentiefen besser funktioniert.

Davon abgesehen verlangsamt es oft die Dinge. Wenn eine einzelne Festplatte beispielsweise zwei Dateien gleichzeitig liest oder schreibt, wird sie gezwungen, wiederholt von Datei 1 zu Datei 2 zu suchen.

Zan Lynx
quelle
2

Ich arbeite für Data Expedition, Inc., die, wie Emmad erwähnte, kommerzielle Software für diese Art von Szenario produziert. Die Übertragung von Multithread-Dateien kann Vorteile haben, Sie müssen jedoch Ihre Leistungsengpässe genau kennen.

Jeder Netzwerkpfad enthält mindestens Dutzende von Hardware- und Softwarekomponenten, die die Daten durchlaufen müssen. Der langsamste von allen bestimmt Ihre Geschwindigkeit. Die Art und Weise, wie Sie die Daten verschieben, ändert jedoch das Verhalten dieser Komponenten.

Viele Hintergrundinformationen dazu hier: http://www.DataExpedition.com/support/notes/tn0009.html

Das Ausführen paralleler TCPs kann hilfreich sein, wenn einzelne TCP-Geschwindigkeiten weit unter die Kapazitäten des Netzwerks, der Festplatte und der CPU fallen.

Wenn Sie jedoch Netzwerkgeschwindigkeiten von mehr als zehn Megabit pro Sekunde betrachten, werden durch parallele Datenübertragungen die Festplatten-E / A aufgrund der Überlastung der Festplatte exponentiell reduziert. Es kann schnell zu einem Punkt kommen, an dem der Festplattenzugriff viel langsamer als die Netzwerkkapazität wird. Die Auswahl der richtigen Lese- / Schreibblockgröße kann hilfreich sein, dies hängt jedoch von der jeweiligen Hardware ab. Beachten Sie auch, dass Windows XP / 2003 nur über einen sehr begrenzten Paged-Pool-Speicher verfügt. Dies kann zu Instabilitäten führen, wenn die Geschwindigkeit über 200 Megabit pro Sekunde liegt.

Auf der anderen Seite kann die Ausführung vieler paralleler TCPs die Latenz bis zu dem Punkt erhöhen, an dem einzelne Sitzungen beginnen, ihre Verbindungen zu verlangsamen oder sogar zu trennen, wenn das Netzwerk langsamer als einige zehn Megabit pro Sekunde ist. Auch hier ist es eine Frage des Experimentierens, um herauszufinden, welcher Grad an Parallelität für einen bestimmten Pfad und bestimmte Bedingungen funktioniert.

Eine Multithread-Dateikopie kann daher hilfreich sein, wenn Sie einen bekannten Datenpfad haben und sich die Zeit nehmen können, um die Anzahl der parallelen Sitzungen und Ihre Festplatten-E / A zu optimieren. Es erfordert jedoch, dass Sie sich neu einstellen, wenn sich die Bedingungen ändern, und kann störend sein, wenn Sie es übertreiben. Aus diesem Grund haben wir uns entschieden, parallele Übertragungen in unserer eigenen Software zu vermeiden, genauso wie wir TCP vermeiden.

Seth Noble
quelle
1

Beachten Sie zusätzlich zu den Aussagen Folgendes: - Auf dem Client muss eine Aufgabe vorhanden sein, um die Chunks zu erstellen, und auf dem Server eine weitere, um sie wieder als eine Datei zusammenzusetzen. Dies erfordert einige Arbeit.

  • Eine gute Sache bei kleinen Blöcken ist, dass Sie Teile einer Datei erneut senden können, wenn der Prozess fehlschlägt, anstatt die große Datei überall zu senden.

  • Ziehen Sie in Betracht, eine größere Leitung zwischen Ihrem Client und dem Server anzufordern.

  • Ziehen Sie in Betracht, die große Datei vor dem Senden zu komprimieren (ich bin mir nicht sicher, ob dies bei Multimedia-Dateien hilfreich wäre, da sie manchmal bereits komprimiert sind).

  • Erwägen Sie die Verwendung eines kommerziellen Dateiübertragungsdienstprogramms wie:

DataExp

Keine Chance
quelle
0

Wenn Sie über eine große Datei sprechen, hilft Multithreading nicht wirklich. Sie werden E / A-gebunden sein, sodass die Verwendung eines einzelnen Threads DIESEN Upload nicht verlangsamt.

Was Sie jedoch möglicherweise befürchten müssen, ist ein Ressourcenkonflikt (vorausgesetzt, Sie schreiben auch den Server). Wenn Sie den Upload in dem Thread bearbeiten, der auch neue Anforderungen akzeptiert und verarbeitet, warten andere Anforderungen. Solange Sie in die Auswahlwarteschlange zurückkehren, nachdem Sie einen Block aus dem Socket gelesen und auf die Festplatte geschrieben haben, sollte es Ihnen gut gehen.

Sarumont
quelle
0

Wenn Sie das, was Sie vorschlagen, auf naive Weise tun, wird Ihr Durchsatz beeinträchtigt. Der Choke-Punkt ist die Festplatten-E / A und das Nichtvorbereiten von Dateien.

Ich werde vorschlagen, einen Thread zu verwenden, der Dateien zum Arbeiten empfängt und sie für die Kopie in die Warteschlange stellt. Anschließend wird eine sequentielle Kopie für alle Elemente in der Warteschlange ausgeführt. Ihr Lieferanten-Thread ist dafür verantwortlich, dass die gelesenen Dateien in die Warteschlange gestellt werden. Auf diese Weise wird das Dateisystem auf den freigegebenen Laufwerken nicht zerstört, und Sie erstellen keine Dateien nacheinander mit Lücken, um die nächsten vorzubereiten. Sie bereiten sie vor und senden sie gleichzeitig.

Der Bonus ist, dass es nur einen Synchronisationspunkt in der Warteschlange gibt, über den Sie sich Sorgen machen müssen.

Patrick Hughes
quelle
0

Anstatt das parallele Hochladen selbst zu implementieren, können Sie vorhandene Protokolle und Tools in Betracht ziehen. ZB das FTP-Protokoll und das Lftp-Tool (Lftp kann mehrere Dateien parallel übertragen).

Daher ist es wahrscheinlich viel einfacher und robuster, lftp-Skripte zu verwenden oder lftp von Ihrer Anwendung aus zu steuern, anstatt alles von Grund auf neu zu implementieren.

Giorgio
quelle
0

Es hängt alles davon ab, wo der begrenzende Faktor liegt.

Multithreading kann hilfreich sein, wenn es zu Umlaufverzögerungen oder anderen Übertragungslücken kommt und die Threads dazu beitragen, die Lücken zu schließen.

Multithreading kann schaden, wenn es dazu führt, dass Ihre Festplatte hin und her klappert und versucht, alle mit Daten versorgten Threads beizubehalten.

usw.

ddyer
quelle