Forum: Mikrocontroller und Digitale Elektronik littleFS Performance / Sehr viele Lesezugriffe nach dem Anlegen einer neuen Datei


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von ch (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen STM32 mit ext. NAND-Flash. Hier kann ich über die 
HAL-Funktionen von ST lesend und schreibend zugreifen (jeweils 2kB) 
sowie löschen (64x2kB). Nun habe ich littleFS eingebunden um mir die 
Datenverwaltung auf dem Flash einfacher zu machen. Das hat soweit auch 
super funktioniert und das Beispiel welches dabei ist mit dem 
Boot-Counter hat funktioniert.

Nun möchte ich viele Dateien mit jeweils wenig Inhalt anlegen (ca. 800, 
meistens nur 1-12 Byte). Nachdem aber ca. 20 angelegt wurden dauert das 
Erstellen einer Datei ab und zu (das schließen, denn da wird erst auf 
das Flash geschrieben) sehr lange. Hier liest littleFS ein paar sektoren 
vielfach aus und nach der Zeit hat das ganze aber auch erfolgreich 
funktioniert. Obwohl die Dateigröße jeweils fast gleich ist passiert das 
nur ab und zu. Teils sind es 6000 Lesezugriffe auf die selbe Page.

Meine littleFS-Konfiguration sieht so aus:
1
const struct lfs_config cfg = {
2
        // block device operations
3
        .read  = Hal_Memory_LFS_Block_Read,
4
        .prog  = Hal_Memory_LFS_Block_Prog,
5
        .erase = Hal_Memory_LFS_Block_Erase,
6
        .sync  = Hal_Memory_LFS_Block_Sync,
7
8
        // block device configuration
9
        .read_size = 2048, // page read is 2048 bytes
10
        .prog_size = 2048, // page program is 2048 bytes
11
        .block_size = 131072, // 64 pages per block -> 64 * 2048 bytes
12
        .block_count = 512, // 512 pages used for littlefs
13
        .cache_size = 2048, // cache buffer in RAM
14
        .lookahead_size = 2048, // lookahead buffer in RAM
15
        .block_cycles = 500,
16
        .read_buffer = (void *) Core_Datamanager_lfs_Readcache,
17
        .prog_buffer = (void *) Core_Datamanager_lfs_Progcache,
18
        .lookahead_buffer = (void *) Core_Datamanager_lfs_Lookaheadcache,
19
};

Bei dem github-Repo von littleFS sind ein paar Issues die in eine 
ähnliche Richtung gehen, aber weder eine Erklärung noch ein 
Lösungsansatz.

Hat jemand von euch littleFS erfolgreich im Einsatz? Aktuell habe ich 
keinen Ansatz den ich verfolgen kann.

Viele Grüße,
ch

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ch schrieb:

> Nun möchte ich viele Dateien mit jeweils wenig Inhalt anlegen (ca. 800,
> meistens nur 1-12 Byte). Nachdem aber ca. 20 angelegt wurden dauert das
> Erstellen einer Datei ab und zu (das schließen, denn da wird erst auf
> das Flash geschrieben) sehr lange. Hier liest littleFS ein paar sektoren
> vielfach aus und nach der Zeit hat das ganze aber auch erfolgreich
> funktioniert. Obwohl die Dateigröße jeweils fast gleich ist passiert das
> nur ab und zu. Teils sind es 6000 Lesezugriffe auf die selbe Page.

Ich habe den Code von LittleFS nicht analysiert, aber selber mal sowas 
Ähnliches geschrieben. Und wenn ich das in Systemen einsetze, bei denen 
der RAM sehr beschränkt ist, dann passiert genau dasselbe.

Das Problem ist dabei einfach, dass letztlich eine hierarchische 
Verwaltungsstruktur umgesetzt werden muss und die Blockgröße der 
Varwaltungsinformationen natürlich der Blockgröße des Targets 
entspricht. Reicht nun der RAM nicht, um wenigstens 2..3 Blöcke zu 
cachen, führt das unweigerlich dazu, dass bei der Erstellung der 
nächsten "Generation" die Daten des alten Rootblocks immer und immer 
wieder eingelesen werden müssen, weil der zwischenzeitlich aus dem Cache 
geflogen ist. Bei Nodes in tieferen Schichten der Hierarchie passiert 
das genauso, nur schon sehr viel seltener und fällt deswegen nicht so 
auf.

Also: einzige Abhilfe ist ein größerer Cache im RAM. Wenn du Glück hast, 
hast du erstens genug RAM um den zu realisieren und zweitens bietet 
dieses LittleFS eine Konfigurationsoption, um den als Cache nutzbar zu 
machen.

Mein FS kann das jedenfalls ;o) Meine Targets haben aber leider oft 
nicht genug RAM, so dass ich diese Fähigkeit oft nicht nutzen kann. :o(

von ch (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Danke für deine Antwort. RAM hab ich genügend, da schaue ich mal ob ich 
noch was rausholen kann.
Sind hier keine littleFS-Nutzer unterwegs?

Viele Grüße

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe LittleFS testweise zusätzlich zum FAT in einem HTTP Server mit 
STM32F407, aber da bisher nur 33 Dateien drin und da macht es keine 
Probleme. Es ist die Mbed Komponente, aber die benutzt ja den gleichen 
Code, ist aus dem gleichen Haus.
Damit kann man aber schnell einen Test bauen, ich habe gerade einen F411 
mit 128 MBit Flash angeklemmt. Das würde das Problem vermutlich nur 
bestätigen.
Es gibt auch schon ein LittleFS2, das habe ich aber noch nicht benutzt 
und kann nicht sagen was da verbessert/geändert wurde. Das liegt auch 
als Branch in dem Repo.

von ch (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das ist interessant. Bei mir passiert alle 32 Dateien etwas was 
hunderte/tausende Lesezugriffe auf die selben paar Pages braucht.

Ich habe jetzt mal alle Caches stark erhöht und es geht wohl jetzt auch 
ein wenig schneller (nicht gemessen). Das Problem löst es aber trotzdem 
nicht...

Viele Grüße,

von Johannes S. (jojos)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das mal auf dem F411 laufen lassen, ein kleines Testprogramm 
mit Mbed-os 6.1.0 das 1000 Dateien á 12 Byte schreibt.
Mit LFS gehen die Zeiten recht linear hoch, wird dann schneller um 
wieder linear anzusteigen.
Da LFSv2 auch schon implementiert ist und nur eine Zeile geändert werden 
muss, habe ich das auch laufen lassen. Erstmal ist es für wenige Dateien 
deutlich schneller, aber dann hauen heftige zyklische Bedenkzeiten von 
13-14 s rein. Das sieht nicht sauber aus, oder LfsV2 macht da 
irgendwelche Umstrukturierungen?
Für die Buffer habe ich die defaults belassen.
Beim LfsV2 sind lookahead=64 und cache=64.
Beim LfsV1 sind lookahead=512 und readsize=64, cache sehe ich da nicht.
SPI Clock sollte 40 MHz sein, habe ich nicht nachgemessen. Und es ist 
ein Debugbuild, also ohne Optimierung. Aber für den Vergleich sollte das 
reichen, und jetzt könnte man noch mit den Cachewerten spielen. Wenn man 
in LfsV2 die Spitzen wegbekommt wäre es ja gut...

von ch (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für den Test. Bei mir schaut es ähnlich aus, hab aber die Zeiten 
nicht rausgemessen.

Prinzipiell ist das selbe auch hier beschrieben:
https://github.com/ARMmbed/littlefs/issues/203

Ich hab die Caches mal testweise auf 16kB erhöht - es ändert sich 
prinzipiell nicht.

Viele Grüße

von Johannes S. (jojos)


Bewertung
1 lesenswert
nicht lesenswert
man sollte einen µC wohl einfach nicht mit sovielen Dateien quälen :) 
Bei einer so einer Anfoderung macht es wohl mehr Sinn direkt die Daten 
in eigene Blöcke zu packen oder sowas wie Key-Value Storage zu benutzen.

von c-hater (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Johannes S. schrieb:

> man sollte einen µC wohl einfach nicht mit sovielen Dateien quälen :)

Da ist was dran. Für sehr, sehr viele Anwendungen braucht man nicht 
wirklich ein Dateisystem, wenn man nur mal richtig über die eigentliche 
Aufgabe nachdenkt.

> Bei einer so einer Anfoderung macht es wohl mehr Sinn direkt die Daten
> in eigene Blöcke zu packen

Das ist bei potentiell unzuverlässigem Speicher aber nur höchstens die 
halbe Einsparung. Du sparst damit nur die Filesystemstruktur ein (auf 
Kosten des Speicherbedarfs). Du sparst aber nicht den Layer ein, der die 
Block-Usage verwaltet. Naja, jedenfalls wenn du klug bist, tust du das 
nicht...

> oder sowas wie Key-Value Storage zu benutzen.

Das ist nun wirklich völlige Grütze. Oder ich habe die Idee hinter der 
Idee nicht verstanden. Inwiefern kann Key-Value-Storage die Probleme 
durch unzuverlässigen Flas-Speicher lösen? Magst du das Rätsel auflösen?

von Johannes S. (jojos)


Bewertung
0 lesenswert
nicht lesenswert
c-hater schrieb:
> Inwiefern kann Key-Value-Storage die Probleme
> durch unzuverlässigen Flas-Speicher lösen?

bei 800 Dateien * 12 Byte, mal aufgerundet auf 1024 * 16 Byte wären 16 
kB die noch in den Speicher passen sollten. Diese 16 kB dann in einer 
Datei zyklisch sichern, so langsam wie nötig. Dann kann LFS effizienter 
arbeiten, braucht viel weniger Verwaltung und kann auch sein wear 
levelling einbringen. Setzt natürlich vorraus das sich die Daten nicht 
im Sekundentakt ändern. Oder die Daten so organisieren das nicht soviel 
aufeinmal geschrieben werden muss.
Das hängt aber doch alles von der Anwendung ab, nur 1000 kleine Dateien 
sind sicher keine gute Lösung. Das war aber auch schon mit FAT auf PCs 
früher schon so.
Der Test war für mich auch nur um sehen ob es geht und was passiert 
wenn. LFS V2 scheint jedenfalls auch besser zu sein. Ich habe den Test 
mit Mbed-os nochmal ohne den RTOS Teil gemacht, da kamen Faktor 2 
schnellere Zeiten bei raus obwohl der erste Test auch nur als single 
thread lief.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.