Minimierung von Kopien beim Schreiben großer Daten in einen Socket

8

Ich schreibe einen Anwendungsserver, der Bilder (große Daten) verarbeitet. Ich versuche Kopien zu minimieren, wenn ich Bilddaten an Clients zurücksende. Die verarbeiteten Bilder, die ich an Clients senden muss, befinden sich in Puffern, die aus jemalloc stammen. Die Möglichkeiten, die Daten an den Client zurückzusenden, sind:

1) Einfacher Schreibanruf.

%Vor%

2) Ich erhalte den Puffer durch mmap anstelle von jemalloc, obwohl ich annehme, dass jemalloc bereits den Puffer mit mmap erstellt. Ich mache dann einen einfachen Anruf zum Schreiben.

%Vor%

3) Ich erhalte einen Puffer durch mmap wie zuvor. Ich benutze dann sendfile, um die Daten zu senden:

%Vor%

Es scheint so, als würden (1) und (2) wahrscheinlich dasselbe tun, wenn jemalloc Speicher in erster Linie durch mmap zuweist. Ich bin mir aber nicht sicher (3). Wird dies wirklich zu irgendwelchen Vorteilen führen? Abbildung 4 in diesem Artikel zu Linux-Methoden zum Kopieren von Null deutet darauf hin, dass eine weitere Kopie verhindert werden kann Sendedatei:

  

Es werden keine Daten in den Socket-Puffer kopiert. Stattdessen nur Deskriptoren   mit Informationen über den Aufenthaltsort und die Länge der Daten sind   an den Socket-Puffer angehängt. Die DMA-Engine übergibt Daten direkt   aus dem kernel buffer an die Protokoll-Engine, wodurch die   verbleibende endgültige Kopie.

Das scheint ein Gewinn zu sein, wenn alles klappt. Ich weiß nicht, ob mein mmaped-Puffer als Kernel-Puffer zählt. Ich weiß auch nicht, wann es sicher ist, diesen Puffer wiederzuverwenden. Da fd und length die einzige Sache ist, die an den Socket-Puffer angehängt wird, nehme ich an, dass der Kernel diese Daten tatsächlich asynchron in den Socket schreibt. Wenn ja, was bedeutet die Rückgabe von sendfile? Woher weiß ich, wann ich diesen Puffer wiederverwenden soll?

Meine Fragen sind also:

  1. Was ist der schnellste Weg, große Puffer (Bilder in meinem Fall) in einen Sockel zu schreiben? Die Bilder werden im Speicher gehalten.
  2. Ist es eine gute Idee, sendfile auf einer mmapped Datei aufzurufen? Wenn ja, was sind die Fehler? Führt das überhaupt zu Gewinnen?
Rajiv 15.11.2013, 19:07
quelle

2 Antworten

3

Es scheint, als ob mein Verdacht richtig war. Ich habe meine Informationen aus diesem Artikel erhalten. Zitat daraus:

  

Auch diese Netzwerkschreibsystemaufrufe, einschließlich Sendedatei, könnten und   In vielen Fällen werden die von TCP über die Methode gesendeten Daten zurückgegeben   Anruf wurde bestätigt. Diese Methoden geben so bald wie alle Daten zurück   wird in die Socket-Puffer geschrieben (sk buff) und an das TCP gesendet   Schreibwarteschlange kann die TCP-Engine von diesem Zeitpunkt an alleine verwalten. Im   Mit anderen Worten zum Zeitpunkt sendfile gibt das letzte TCP-Sendefenster zurück   nicht tatsächlich an den Remote-Host gesendet, sondern in die Warteschlange gestellt. In Fällen, in denen   Scatter-Gather-DMA wird unterstützt Es gibt keinen separaten Puffer, der   hält diese Bytes, eher die Puffer (sk buffs) halten nur Zeiger auf   die Seiten des Betriebssystempuffercaches, in denen sich der Inhalt der Datei befindet.   Dies kann zu einer Wettlaufsituation führen, wenn wir den Inhalt der   Datei, die den Daten im letzten TCP-Sendefenster entspricht   Sendedatei wird zurückgegeben. Als Ergebnis kann TCP-Engine neu geschrieben senden   Daten an den Remote-Host statt dessen, was wir ursprünglich beabsichtigten   senden.

Vorausgesetzt, der Puffer aus einer mmapped-Datei wird sogar als "DMA-fähig" betrachtet, scheint es keine Möglichkeit zu geben zu wissen, wann es sicher ist, es ohne explizite Bestätigung (über das Netzwerk) vom tatsächlichen Client wiederzuverwenden. Ich muss vielleicht bei einfachen Schreibanrufen bleiben und die zusätzliche Kopie übernehmen. Es gibt ein Papier (auch aus dem Artikel) mit weiteren Details.

Bearbeiten : Dieser Artikel zum Splice-Aufruf zeigt auch die Probleme. Zitieren:

  

Seien Sie sich bewusst, wenn Sie Daten von einem mmap-Puffer zu einem Netzwerk verbinden   Socket ist es nicht möglich zu sagen, wann alle Daten gesendet wurden. Selbst wenn   splice () kehrt zurück, der Netzwerkstack hat möglicherweise noch nicht alle Daten gesendet. Damit   die Wiederverwendung des Puffers überschreibt möglicherweise nicht gesendete Daten.

    
Rajiv 16.11.2013, 21:24
quelle
1

Für die Fälle 1 und 2 - benötigt die Operation, die Sie als // Speichern von Bilddaten in diesem Puffer markiert haben, eine Konvertierung? Ist es einfach nur aus dem Speicher zu buf kopieren?

Wenn es nur eine einfache Kopie ist, können Sie schreiben direkt auf den Zeiger von jemalloc.

Wenn angenommen wird, dass img ein Zeiger ist, der von jemalloc erhalten wurde und die Größe eine Größe Ihres Bildes ist, führen Sie einfach folgenden Code aus:

%Vor%

Es funktioniert ordnungsgemäß zum Blockieren von E / A (Standardverhalten). Wenn Sie Daten in einer nicht blockierenden Weise schreiben müssen, sollten Sie in der Lage sein, den Code selbst zu überarbeiten, aber jetzt haben Sie die Idee.

Für Fall 3 - sendfile dient zum Senden von Daten von einem Deskriptor zu einem anderen. Das bedeutet, dass Sie beispielsweise Daten direkt von der Datei an den TCP-Socket senden können und keinen zusätzlichen Puffer reservieren müssen. Also, wenn das Bild, das Sie an einen Client senden möchten, in einer Datei ist, gehen Sie einfach für eine Sendedatei. Wenn Sie es im Speicher haben (weil Sie es irgendwie verarbeitet haben oder nur generiert haben), verwenden Sie den oben erwähnten Ansatz.

    
ArturFH 16.11.2013 20:48
quelle

Tags und Links