1

Is there a limit for short strings where using the F() macro brings more RAM overhead then saving?

For (a contrived) example:

Serial.print(F("\n"));
Serial.print(F("Hi"));
Serial.print(F("there!"));
Serial.print(F("How do you doyou how?"));

Would any one of those be more efficient without the F()?

I imagine it uses some RAM to iterate over the string and copy it from PROGMEM to RAM. I guess the question is: how much? Also, is heap fragmentation a concern here?

I'm looking at this purely from SRAM-conserving perspective.

Community
  • 1
  • 1
frnhr
  • 12,354
  • 9
  • 63
  • 90
  • F() macro is using for store string in flash memory, a complete documentation can be see to http://playground.arduino.cc/Learning/Memory. Depends how you want to use your string you can think about speed of access for flash or sram, for this you can see http://arduino.stackexchange.com/questions/221/what-can-i-do-if-i-run-out-of-flash-memory-or-sram. – Mihai8 Aug 23 '15 at 15:01
  • @user1929959 The "complete documentation" has a full one sentence on the `F()` macro. I made clear that "I'm looking at this purely from SRAM-conserving perspective" in my question. – frnhr Aug 23 '15 at 15:13
  • The only correct answer is *it depends* therefore this is off-topic: opinion based and too broad in that explaining how to profile this would take more than is allowed in the answer box. –  Feb 06 '16 at 01:10
  • @JarrodRoberson Care to elaborate a bit? I think it's pretty deterministic, not opinion-based at all. – frnhr Feb 06 '16 at 01:19

2 Answers2

1

From a purely SRAM-conserving perspective all of your examples are identical in that no SRAM is used. At run-time some RAM is used, but only momentarily on the stack. Keep in mind that calling println() (w/o any parameters) uses some stack/RAM.

For a single character it will take up less space in flash if a char is passed into print or println. For example:

Serial.print('\n');

The char will be in flash (not static RAM).

Using

Serial.print(F("\n"));

will create a string in flash memory that is two bytes long (newline char + null terminator) and will additionally pass a pointer to that string to print which is probably two bytes long.

Additionally at runtime, using the F macro will result in two fetches ('\n' and the null terminator) from flash. While fetches from flash are fast, passing in a char results in zero fetches from flash, which is a tiny bit faster.

abh
  • 453
  • 3
  • 11
0

I don't think there is any minimum size of the string to be useful. If you look at how the outputting is implemented in Print.cpp:

size_t Print::print(const __FlashStringHelper *ifsh)
{
  PGM_P p = reinterpret_cast<PGM_P>(ifsh);
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}

You can see from there that only one byte of RAM is used at a time (plus a couple of variables), as it pulls the string from PROGMEM a byte at a time. These are all on the stack so there is no ongoing overhead.

I imagine it uses some RAM to iterate over the string and copy it from PROGMEM to RAM. I guess the question is: how much?

No, it doesn't as I showed above. It outputs a byte at a time. There is no copying (in bulk) of the string into RAM first.

Also, is heap fragmentation a concern here?

No, the code does not use the heap.

Nick Gammon
  • 1,173
  • 10
  • 22