2008-10-10 22 views
5

Ich schreibe eine kleine Anwendung, die JPEG-Bilder mit einer konstanten Rate auf einer SD-Karte schreibt. Ich wählte ein EXT3-Dateisystem, aber das gleiche Verhalten wurde mit einem EXT2-Dateisystem beobachtet.SD-Karte schreiben Leistung

Mein Schreiben Schleife sieht wie folgt aus:

get_image() 
fwrite() 
fsync() 

Oder wie folgt aus:

get_image() 
fopen() 
fwrite() 
fsync() 
fclose() 

ich auch einige Timing-Statistiken angezeigt werden, und ich kann mein Programm sehen manchmal mehrere Sekunden lang blockiert. Die durchschnittliche Rate ist immer noch gut, denn wenn ich die eingehenden Bilder in einem Fifo halte, dann werde ich viele Bilder in einem kurzen Zeitraum nach einem solchen Stand schreiben. Weißt du, ob es ein Problem mit dem Betriebssystem ist oder ob es mit der SD-Karte selbst zusammenhängt? Wie könnte ich näher an Echtzeit heranrücken? Ich brauche keine starke Echtzeit, aber für einige Sekunden blockiert zu sein, ist nicht akzeptabel.

Einige Präzision: Ja, es ist notwendig, nach jeder Datei Fsync, weil ich das Bild möchte auf der Festplatte sein, nicht in einem Benutzer oder Kernel-Puffer. Ohne FSyncing, habe ich viel besser, aber immer noch inakzeptabel Stall. Ich glaube nicht, dass es sich um ein Pufferproblem handelt, da die erste Blockade auftritt, nachdem 50 MB geschrieben wurden. Und gemäß der man-Seite ist fsync genau hier, um sicherzustellen, dass keine Daten gepuffert sind.

Genauigkeit in Bezug auf die durchschnittliche Schreibrate: Ich schreibe mit einer Rate, die durch die Karte, die ich verwende, nachhaltig ist. Wenn ich ein eingehendes Bild anhake, während ich darauf warte, dass ein fsync abgeschlossen wird, dann wird nach dieser Blockierung die Schreibübertragungsrate zunehmen und ich werde schnell wieder zur Durchschnittsrate zurückkehren. Die durchschnittliche Übertragungsrate beträgt etwa 1,4 MB/s.

Die systeme ist ein modernes Laptop Ubuntu 8.04 mit Lager kee (2.6.24.19)

Antwort

1

Ich bin nicht sehr gut informiert in diesem Bereich laufen, aber die Symptome, die Sie sehr viel beschreiben klingen wie ein Puffer füllt. Möglicherweise füllen Sie einen Puffer im Dateischreiber oder im E/A-Gerät, das mit der SD-Karte selbst kommuniziert. Sie müssen dann warten, bis die Daten tatsächlich auf die Karte geschrieben werden (und damit den Puffer leeren), bevor Sie mehr schreiben können. SD-Karten sind keine besonders schnellen Brenner. Wenn Sie herausfinden können, ob während dieser Pausen tatsächlich Daten auf die Karte geschrieben werden, würde dies meine Theorie bestätigen. Einige Kartenleser haben eine LED, die blinkt, wenn auf Daten zugegriffen wird - das wäre wahrscheinlich ein guter Indikator.

nur eine Ahnung ... nehmen Sie es mit etwas Salz :)

3

Ist es notwendig, fsync() nach jeder Datei? Sie haben vielleicht mehr Glück, wenn das Betriebssystem entscheidet, wann es sinnvoll ist, alle Bilder in der Warteschlange auf die SD-Karte zu schreiben (die Anschaffungskosten für die Manipulation des SD-Kartensystems über viele Bilder zu erhöhen, anstatt sie für jedes Bild zu übernehmen).

Können Sie weitere Details zu Ihrer Plattform angeben? Langsame E/A-Zeiten können mit anderen Prozessen auf dem System, einem langsamen E/A-Controller usw. zusammenhängen.

Sie können auch ein Dateisystem in Betracht ziehen, das besser dafür geeignet ist, wie Flash-Speicher funktioniert. FAT32 ist häufiger als extN, aber ein Dateisystem, das speziell für SD gebaut wurde, kann ebenfalls in Ordnung sein. JFFS ist ein gutes Beispiel dafür.Sie werden wahrscheinlich mit einem Dateisystem, das für Flash entwickelt wurde, bessere Leistung erzielen (im Gegensatz zu magnetischen Medien), und Sie erhalten bessere Wear-Leveling-Eigenschaften (und damit auch die Lebensdauer des Geräts/Zuverlässigkeit).

+0

pleaes beachten JFFS und dergleichen sind nicht eine gute Idee für einige Flash-Geräte, wie Compactflash, die ihre eigenen Wear Leveling tun. – Hasturkun

+1

Sind sie eine schlechte Idee, oder nutzt der CompactFlash-Wear-Leveling nur die Vorteile von JFFS? Es ist eine ehrliche Frage, ich habe keine Ahnung. Ich stimme zu, dass es sicherlich eine bessere Wahl für "rohe" Flash-Geräte ist. –

2

AFAIK einige Flash-Festplatten haben wirklich schlechte Schreibleistung (vor allem billige Marken). Wenn Sie also die Schreibgeschwindigkeit Ihrer Anwendung messen (einschließlich der Zeit, die für fsync benötigt wird), was bekommen Sie? Es kann leicht in der Größenordnung von wenigen Megabyte pro Sekunde liegen - nur weil die Hardware nicht besser ist.

Auch das Schreiben kann viel langsamer sein, wenn Sie viele kleine Blöcke statt eines großen Blocks schreiben (die Flash-Disk kann in schlechten Fällen nur etwa 10 Schreibvorgänge pro Sekunde erledigen). Dies ist wahrscheinlich etwas, das durch den Kernel-Puffer gemildert werden kann, so dass die Verwendung von fsync häufig das Schreiben verlangsamen kann.

Btw. Haben Sie die Schreibleistung auf FAT32 gemessen? Ich denke, es ist ungefähr das Gleiche, aber wenn nicht, ist vielleicht noch Optimierung vorhanden?

1

Kann dies helfen - Benchmarking Filesystems:

... Ich war ziemlich überrascht, wie langsam ext3 war insgesamt so viele Distributionen verwenden dieses Dateisystem als Standard-Dateisystem ...

und "ext3 fsync batching":

... Dieser Patch misst die Zeit, um eine Transaktion zu der Platte zu begehen nimmt, und schläft auf der Geschwindigkeit des darunterliegenden Platte basiert.

4

Versuchen Sie, die Datei mit O_DIRECT zu öffnen, und führen Sie das Caching in Anwendungsebene aus.

Das gleiche Problem trat auf, als wir eine PVR-Funktion (Personal Video Record) in STB Box implementierten. Der O_DIRECT Trick erfüllt unser Bedürfnis finaly. (*)

Ohne O_DIRECT. Die Daten von write() werden zuerst im Kernel-Puffer zwischengespeichert und dann beim Aufruf von fsync oder wenn der Kernel-Cache-Puffer voll ist (**).

Mit O_DIRECT .TH Kernel DMA tun direkt auf den physikalischen Speicher durch den User-Space-Puffer als Parameter an die write syscalls weitergegeben hingewiesen. Es wird also keine CPU- und mem-Bandbreite in den Kopien zwischen dem Userspace-Speicher und dem Kernel-Cache geben, und es wird keine CPU-Zeit im Kernel für die Verwaltung des Cache (wie Cache-Lookups, pro-Seite-Sperren usw.) benötigt. (kopiert von here)

Nicht sicher, es kann auch Ihr Problem lösen, aber Sie möchten vielleicht einen Versuch haben.

* Trotz Linus critize von O_DIRECT, löste es unsere Probleme.

**: Angenommen, Sie die Datei nicht mit O_DSYNC oder O_SYNC

+0

Sehr interessant. Ich denke, das Problem beim Caching ist, dass alle E/A-Anforderungen (auf diesem bestimmten System) eine einzige Warteschlange durchlaufen. Wenn ein Blockgerät (die Festplatte) seine Journaling-Informationen löscht, wird das nicht verwandte Schreiben auf ein anderes Blockgerät (SD-Karte) blockiert. Ich werde diese O_DIRECT-Sache versuchen. – shodanex

0

Für alle, die dies lesen und mit einem Kernel 2.6.28 oben geöffnet hat, ist die Empfehlung ext4 zu verwenden, anstatt ext3, das ist ein Dateisystem, das Sie ist Kann für bessere Leistung stimmen. Die beste Leistung wird im Data = Writeback-Modus erzielt, in dem Daten nicht aufgezeichnet werden. Lesen Sie den Abschnitt Datenmodus von https://www.kernel.org/doc/Documentation/filesystems/ext4.txt.

Wenn Sie eine Partition bereits erstellt haben, sagen /dev/sdb1, dann sind einige Schritte, die verwendet werden können, es mit ext4 zu formatieren, ohne Journaling:

mkfs.ext4 /dev/sdb1 -L jp # Creates the ext4 filesystem 
tune2fs -o journal_data_writeback /dev/sdb1 # Set to writeback mode 
tune2fs -O ^has_journal /dev/sdb1 # Disable journaling 
sudo e2fsck -f /dev/sdb1 # Filesystem check is required 

Dann können Sie diese Partition mounten (oder einen Satz ein Eintrag /etc/fstab, wenn Sie wissen, was Sie tun) mit dem entsprechenden Flags:

mount -t ext4 -O noatime,nodirame,data=writeback /dev/mmcblk0p1 /mnt/sd 

Umzug von ext3 zu einem optimierten ext4-Dateisystem sollte ein drastischer Unterschied. Und natürlich, wenn Ihre SD-Karte schneller ist, sollte das helfen (d.h. Klasse 10).

Siehe auch https://developer.ridgerun.com/wiki/index.php/High_performance_SD_card_tuning_using_the_EXT4_file_system