Forum: Compiler & IDEs AVR Libc Speicher stats


von Sebastian Schildt (Gast)


Lesenswert?

Hallo!

Ich brauche mal ein wenig Hilfe. Es geht um folgendes: Ich möchte genau
wissen wieviel Speicher mein Programm verbraucht.
Bis jetzt glaube ich folgendes zu wissen:
Alle meine globalen Variablen (also nicht ge- malloc'te Sachen die
irgendwo in den Headern rumfliegen) müssen ja eh immer im RAM liegen,
d.h. der Verbrauch ist schon zu Compile Zeit bekannt. Sehe ich das
richitg, dass ich die Größe über die Werte

  .data        154   8388704
+ .bss          44   8388858

raus bekomme? Also hier 154+44. Was ist der Unterschied zwischen .data
und .bss? Die Werte sind in Byte?


Jetzt kommt der kompliziertere Teil: Sachen die zur Laufzeit mit malloc
allokiert werden. Ich könnte natürlich durch den Code gehen und per
Hand zählen, aber da das ganze ein Laufzeitsystem mit mehreren
Prozessen ist, könnte das unübersichtlch werden, daher wollte ich gerne
in meinem Debug Kompilat eine memstat() Routine einbauen, die ie Größe
des Heap über die serielle Schnittstelle ausgibt.

Ich habe "Using malloc()" sowie die malloc() Beschreibung aus der
avr-libc Doku gelesen und mit wenig Erfolg versucht Variablen wie
__malloc_heap_start o.ä per sprintf zu formatieren und rauszugeben. Das
ganze mit recht wenig Erfolg :(

Das Ziel ist sowas wie: "Heap beginnt an Adresse xx und endet bei
yyy."

Geht das überhaupt mit der libc, oder müsste ich mir dazu eine eigene
Speicherverwaltung schreiben bzw. malloc/free wrapper die mit zählen?

So, das war lang, aber vielleicht hat jemand einen Tipp für mich!

MfG

Sebastian

von Jörg Wunsch (Gast)


Lesenswert?

> Was ist der Unterschied zwischen .data und .bss?

Müßte eigentlich sogar in der Doku stehen: .data sind die
initialisierten Daten, .bss die nichtinitialisierten Daten (genauer:
die Bereiche, die beim Start ausgenullt werden sollen).

Käme noch .noinit hinzu, muß explizit angefordert werden (via
_attribute_), verhält sich wie .bss, wird aber gar nicht
initialisiert, so daß es einen Reset des Controllers überlebt.

> Die Werte sind in Byte?

Ja, die GNU-Tools messen immer alles in Bytes, egal, ob die CPU 8-,
16-, 32- oder 64-bittig orientiert ist.  Die Wordomanie von Atmel ist
sowieso nicht zu verstehen, besonders wenn man bedenkt, daß LPM & Co.
am Ende wieder byteorientiert sind.

> Jetzt kommt der kompliziertere Teil: Sachen die zur Laufzeit mit
> malloc allokiert werden.

Noch komplizierter: den Stackverbrauch ermitteln.  Außer der Methode:
,,ich beschreibe den RAM erstmal mit 42 und sehe dann regelmäßig nach,
bis wohin der Stack das wieder überschrieben hat'' gibt's kaum eine
Variante, wie man den Stackverbrauch so recht ausrechnen kann.

Für malloc() haben auch andere Leute schon nach einem API gefragt, wie
man statistische Daten zurückbekommen kann.  Da muß ich mir mal was
einfallen lassen...  Derzeit haben die dazu benutzten Variablen
`static linkage' innerhalb von malloc.c, d. h. sie sind zwar für
Debugger einsehbar, nicht aber für den Rest der Applikation.  Das wird
sich zwar ändern, wenn ich mal dazu komme, meine realloc()-
Implementierung endlich einzubringen (dann müssen die entsprechenden
Variablen zwischen mehreren Bibliotheksmodulen kommunziert werden
können, damit können sie keine static linkage mehr haben), aber ich
möchte dennoch nicht erst einreißen lassen, daß Applikationen sich auf
Interna der Bibliotheksimplementierung verlassen und stattdessen
lieber ein offizielles API für diesen berechtigten Wunsch realisieren.

Vorschläge, was in so ein API alles reinkommen kann, werden gern
entgegengenommen.  Außer der höchsten durch malloc() beanspruchten
Speicheradresse kann ich mir noch vorstellen, daß die Leute an der
Menge an Speicher interessiert sein könnten, der sich auf der free
list angesammelt hat, um so ein Gefühl zu bekommen, wie sich die
Fragmentierung über die Zeit entwickelt.

Derzeit bleibt wohl als einzige Variante, daß Du Dir malloc.c aus dem
Quellcode der Bibliothek rausziehst und testhalber in Deine eigene
Applikation reinnimmst.  Dann kannst Du die entsprechenden Variablen
für Dich intern veröffentlichen.  (Es ist insbesondere brkval, was
Dich da interessiert.)

von Sebastian Schildt (Gast)


Lesenswert?

Hallo!

Danke für die Antworten.
Jetzt weiß ich zumindest, dass ich die Möglichkeit nicht übersehen
habe. brkval war genau dass, was mich interessierte; ich hatte bloß
keinen Erfolg ranzukommen :) Von "static linkage" hatte ich auf Grund
meiner mittelprächtigen C Kenntnisse noch nix gehört...

Was den Stackverbrauch angeht: Ich kann aber doch jederzeit im Programm
schauen, wo der Stackpointer steht?

Was die Erweiterung der malloc Implementatierung mit einem Statisktik
API angeht: Das würde ich sehr begrüßen. Ich hoffe, dich packt
demnächst irgendwann die Motivation :)

MfG

Sebastian

von Matthias (Gast)


Lesenswert?

Hi

das zyklische Prüfen des Stackpointer bringt spätestens beim Einsatz
von INT's keine exakten Ergebnisse mehr. Besser ist, wie Jörg das
schon schrieb, das komplette SRAM mit einem bestimmten Bitmuster zu
beschreiben und irgendwann mal zu schauen bis wohin dieses Bitmuster
noch existiert.

Matthias

von Sebastian Schildt (Gast)


Lesenswert?

Hi!

Ja, das ist klar. Das Prüfen des SP kann ja nur einen
"Momentaufnahme" sein. Den Höchststand findet man so natürlich nicht.
In diesem Falle ging es mir dann auch eher um eine ungefähre
Vorstellung davon, bis wohin der Stack reicht und ob ich so ca. 30
Bytes oder 2 KB Luft zwischen Stack und Heap habe.

Ich denke mal man bewegt sich hier irgendwann in Bereiche, wo man ohne
aufwendigere Simulationen des Gesamtsystems nicht mehr weiter kommt.

MfG

Sebastian

von Malte _. (malte) Benutzerseite


Lesenswert?

Hallo,
gibt es hier nach fast 1,5Jahren inzwischen neues?
Wenn ich das richtig sehe ist realloc() ja inzwischen dazugekommen,
aber
brkval kennt der Compiler weiterhin nicht.
Ich bin bisher soweit, dass SP periodisch in einem Interrupt
aufgerufen wird und der minimale Wert in einer Variable gespeichert
wird und bei der Displayausgabe hiervon noch __malloc_heap_start
abgezogen wird.
Bisherige Erkentnis: 2KB RAM reichen bei meiner Anwendung, bei 1KB RAM
könnte es aber eventuell Probleme geben.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

brkval heißt jetzt __brkval und ist global, damit solltest du
(undokumentiert) darauf zugreifen können.

Ich hätte nichts gegen ein memstat()-Interface oder sowas, allerdings
müssten sich interessierte ,,Kunden'' da erstmal äußern, was da
alles
genau drin sein soll.  Was nicht geht: die gerade belegten
Speicherblöcke durchlaufen, zählen usw.  Was geht: die größe des
derzeitigen Heap ermitteln, die gerade freigegebenen Blöcke
durchzählen usw.  Die Differenz zwischen beiden wäre dann die
Gesamtspeichermenge der gerade aktiven Blöcke.

von Malte _. (malte) Benutzerseite


Lesenswert?

__brkval kennt er bei mir nicht. Ich vermute avr-libc 1.2.3 einfach
schon zu alt :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Doch, realloc() ist in allen 1.2er Versionen dabei.

Natürlich darfst du nicht erwarten, dass __brkval irgendwo für dich
deklariert wäre ;-), es gehört ja zu den Systeminterna und ist daher
nicht offiziell exportiert.  Wie geschrieben, ich bin für Vorschläge
für ein memstat() offen (dann aber bitte auf der avr-libc-dev Liste).

extern char *__brkval;

ist die intern benutzte Deklaration (aber das hast du sicher im
Sourcecode inzwischen selbst nachgelesen wink).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.