Go Down

Topic: Programmoptimierung: SRAM sparen (Read 1 time) previous topic - next topic

-Jan-

Hallo zusammen,

da der Code für mein aktuelles Projekt schon fast fertig ist und auch alles prima läuft, möchte ich das Programm an einigen Stellen optimieren.

In meinem Programm verwende ich sehr oft das ASCII-Zeichen 59 (Semikolon). Nun würde mich mal interessieren, welches der 3 Testprogrammen am effektivsten und RAM-schonenden ist.

Version 1:
Code: [Select]

client.print(test);
client.print(F(";"));
client.print(test1);
client.print(F(";"));
client.print(test2);
client.print(F(";"));
client.print(test3);


Version 2:
Code: [Select]

char semikolon = 59;

client.print(test);
client.print(semikolon);
client.print(test1);
client.print(semikolon);
client.print(test2);
client.print(semikolon);
client.print(test3);


Version 3:
Code: [Select]

#include <avr/pgmspace.h>
prog_uchar PROGMEM semikolon = 59;

client.print(test);
client.print(pgm_read_byte_near(semikolon));
client.print(test1);
client.print(pgm_read_byte_near(semikolon));
client.print(test2);
client.print(pgm_read_byte_near(semikolon));
client.print(test3);


Oder lässt sich sowas noch eleganter und effektiver lösen? (Wie sinnvoll das bei einem Byte ist, sei mal dahingestellt!)

Wie spare ich RAM bei "www.arduino.cc" bei client.connect("www.arduino.cc", 80) ? PSTR-Makro?

Danke und Gruß


guntherb

Welche der Methode am wenigsten RAM verbraucht, kannst du selbst testen:

Am Ende von Setup(), oder in der Loop():
Code: [Select]
  Serial.print("freies RAM: ");Serial.println(freeRam ());

Die Funktion freeRam() sieht so aus:
Code: [Select]
int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

Damit wird das freie Ram am oberen Ende des RAM Bereiches angezeigt.

Grüße
Gunther

jurs


In meinem Programm verwende ich sehr oft das ASCII-Zeichen 59 (Semikolon). Nun würde mich mal interessieren, welches der 3 Testprogrammen am effektivsten und RAM-schonenden ist.


Wenn Du ein char ausgeben möchtest, gibt man normalerweise keinen String (doppelte Hochkommas) aus, sondern ein einzelnes char-Zeichen (einfache Hochkommas):
Code: [Select]
client.print(';');

Ansonsten ist es bei stets derselben Stringkonstante so ziemlich gehupft wie gesprungen:
Code: [Select]
client.print(";");
Das ist eine Stringkonstante von 2 Bytes, und die belegt 2 Bytes RAM, egal ob Du sie im Programm einmal oder 100 mal ausgibst, dafür sorgt der Compiler, wenn Du identische Stringkonstanten mehrfach verwendest.


Serenifly

PSTR() ist lediglich ein Makro für "const PROGMEM char*"

Direkt in eine Funktion eingesetzt funktioniert das daher nur mit Funktionen die direkt einen PROGMEM String verarbeiten können. Das sind oft nur die _P Funktionen in der string.h Library der avr libc.


Ich habe mir noch das gemacht:
Code: [Select]

const int STRING_BUFFER_SIZE = 21;
char stringBuffer[STRING_BUFFER_SIZE];

#define P(str) strcpy_P(stringBuffer, PSTR(str))


P() kann man dann wie F() verwenden. Aber für alle möglichen Funktionen und nicht nur print(). Das kostet natürlich erst mal RAM für den Puffer, aber wenn man viele etwas längere String Konstanten hat (und diese nicht nur für print() benötigt) spart man letztendlich Speicher. Den Puffer kann man außerdem noch für andere Dinge verwenden.

Ob sich das lohnt hängt davon ab was man genau macht. Ist vielleicht etwas speziell. Wenn man nur Ausgaben auf Serial und/oder Ethernet hat bringt es nichts.

-Jan-

Hallo,

vielen Dank für die Tipps!
Ich habe mich für client.print(';') entschieden.
Bei allen anderen Funktionen verwende ich nun das P()-Makro von Serenifly.

Gruß

Go Up