Ich benutze den Funktionsaufruf fwrite()
, um Daten in eine Pipe unter Linux zu schreiben.
Früher wurde fwrite()
wiederholt für kleine Datenblöcke (durchschnittlich 20 Bytes) aufgerufen, und die Pufferung wurde auf fwrite()
beschränkt. strace auf dem Prozess zeigte, dass 4096 Bytes Daten gleichzeitig geschrieben wurden.
Es stellte sich heraus, dass dieser Schreibprozess der Flaschenhals in meinem Programm war. Also beschloss ich, Daten in meinem Code in Blöcke von 64 KB zu puffern und dann den gesamten Block mit fwrite()
zu schreiben. Ich habe setvbuf()
verwendet, um den FILE * -Zeiger auf 'No Buffering' zu setzen.
Die Leistungsverbesserung war nicht so signifikant, wie ich es erwartet hatte.
Noch wichtiger ist, dass die strace
-Ausgabe zeigte, dass Daten immer noch 4096 Bytes gleichzeitig geschrieben wurden. Kann mir bitte jemand dieses Verhalten erklären? Wenn ich fwrite()
mit 64KB Daten anrufe, warum schreibt es dann nur 4096 Bytes gleichzeitig?
Gibt es eine Alternative zu fwrite()
für das Schreiben von Daten in eine Pipe mit einem FILE * -Zeiger?
Die 4096 kommt von den Linux-Maschinen, die Pipelines zugrunde liegen. Es gibt zwei Stellen, an denen es auftritt. Einer ist die Kapazität der Pipeline. Die Kapazität ist eine Systemseite auf älteren Versionen von Linux, die 4096 Byte auf einer 32-Bit-i386-Maschine ist. (Bei moderneren Versionen von Linux ist die Kapazität 64 KB.)
Der andere Ort, an dem Sie das 4096-Byte-Problem finden, ist die definierte Konstante PIPE_BUF
, die Anzahl der Bytes, die garantiert atomar behandelt werden. Unter Linux sind das 4096 Bytes. Was dieses Limit bedeutet, hängt davon ab, ob Sie die Pipeline auf blockierend oder nicht blockierend eingestellt haben. Mach einen man -S7 pipe
für alle blutigen Details.
Wenn Sie große Datenmengen mit hoher Geschwindigkeit austauschen möchten, sollten Sie Ihre Verwendung von Pipes überdenken. Sie befinden sich in einer Linux-Box, daher ist geteilter Speicher eine Option. Sie können Pipes verwenden, um relativ kleine Datenmengen als Signalmechanismus zu senden.
Wenn Sie das Pufferungsverhalten ändern wollen, müssen Sie dies unmittelbar nach dem fopen
(oder vor jedem I / O, für die Standard-Dateihandles stdin
, stdout
, stderr
) tun. Sie möchten auch nicht die Pufferung deaktivieren und versuchen, den Puffer selbst zu verwalten. Geben Sie stattdessen Ihren 64 KB-Puffer an setvbuf
an, damit er ordnungsgemäß verwendet werden kann.
Wenn Sie die Pufferung wirklich manuell verwalten möchten, verwenden Sie nicht stdio
; Verwenden Sie die niedrigeren Aufrufe open
, write
und close
.