Where does PROGMEM stuff go?

Back in my early work with arduino, I learnt I was supposed to put hardcoded strings into PROGMEM. Great - i could suddenly fill my sketches and logfiles with lots of useful messages.

I've recently hit some problems with a previously working sketch and have been led to believe it may be down to using too much PROGMEM, or to the compilier writing it to the wrong place. (something to do with a 64k limit???? - not sure of the details). Anyway, the result is I decided to try to prune some of the cr4p I'd left lying about in the file I keep all my PROGMEM stuff in.

Before I started purging, when I compiled my project I got the following (on a Mega 2560 compiled on version 1.0).....

Binary sketch size: 128420 bytes (of a 258048 byte maximum)

I then removed some of my redundant PROGMEM statements with a precompiler directive....

//#define WASTE_OF_SPACE
#ifdef WASTE_OF_SPACE
  const prog_char IGC_LINE_001[] PROGMEM = "B1255275225709N00105715WA006780074700309";
  const prog_char IGC_LINE_002[] PROGMEM = "B1255315225644N00105791WA006750074500310";
  const prog_char IGC_LINE_003[] PROGMEM = "B1255355225559N00105822WA006780074300310";
  const prog_char IGC_LINE_004[] PROGMEM = "B1255395225479N00105779WA006830074900310";
  const prog_char IGC_LINE_005[] PROGMEM = "B1255435225439N00105682WA006830074900210";
  const prog_char IGC_LINE_006[] PROGMEM = "B1255475225453N00105595WA006830074600210";
  const prog_char IGC_LINE_007[] PROGMEM = "B1255515225496N00105563WA006860074900211";
  const prog_char IGC_LINE_008[] PROGMEM = "B1255555225538N00105554WA006870075200211";
  const prog_char IGC_LINE_009[] PROGMEM = "B1255595225567N00105615WA006900075300210";
  const prog_char IGC_LINE_010[] PROGMEM = "B1256035225535N00105703WA006940075900210";
  const prog_char IGC_LINE_011[] PROGMEM = "B1256075225455N00105720WA006950076000210";
  const prog_char IGC_LINE_012[] PROGMEM = "B1256115225389N00105648WA006950076000209";
  const prog_char IGC_LINE_013[] PROGMEM = "B1256155225372N00105548WA007050076800211";
  const prog_char IGC_LINE_014[] PROGMEM = "B1256195225398N00105485WA007010076800210";
  const prog_char IGC_LINE_015[] PROGMEM = "B1256235225440N00105489WA007010076300211";
  const prog_char IGC_LINE_016[] PROGMEM = "B1256275225465N00105556WA007070076900211";
  const prog_char IGC_LINE_017[] PROGMEM = "B1256315225439N00105646WA007140077600211";
  const prog_char IGC_LINE_018[] PROGMEM = "B1256355225365N00105678WA007210078600211";
  const prog_char IGC_LINE_019[] PROGMEM = "B1256395225297N00105611WA007210078600210";
  const prog_char IGC_LINE_020[] PROGMEM = "B1256435225280N00105510WA007290079100211";
  const prog_char IGC_LINE_021[] PROGMEM = "B1256475225307N00105448WA007290079400210";
  const prog_char IGC_LINE_022[] PROGMEM = "B1256515225347N00105460WA007350079700211";
  const prog_char IGC_LINE_023[] PROGMEM = "B1256555225358N00105534WA007420080400210";
  const prog_char IGC_LINE_024[] PROGMEM = "B1256595225312N00105608WA007470081200209";
  const prog_char IGC_LINE_025[] PROGMEM = "B1257035225233N00105607WA007540081500211";
  const prog_char IGC_LINE_026[] PROGMEM = "B1257075225173N00105528WA007550081900210";
  const prog_char IGC_LINE_027[] PROGMEM = "B1257115225168N00105427WA007530081700211";
  const prog_char IGC_LINE_028[] PROGMEM = "B1257155225209N00105390WA007580081900211";
  const prog_char IGC_LINE_029[] PROGMEM = "B1257195225241N00105441WA007620082500210";
  const prog_char IGC_LINE_030[] PROGMEM = "B1257235225219N00105536WA007690082900210";
  const prog_char IGC_LINE_031[] PROGMEM = "B1257275225145N00105573WA007740083400210";
  const prog_char IGC_LINE_032[] PROGMEM = "B1257315225072N00105520WA007830084300210";
  const prog_char IGC_LINE_033[] PROGMEM = "B1257355225038N00105419WA007810084300211";
  const prog_char IGC_LINE_034[] PROGMEM = "B1257395225056N00105335WA007820084300209";
  const prog_char IGC_LINE_035[] PROGMEM = "B1257435225099N00105328WA007880084900211";
  const prog_char IGC_LINE_036[] PROGMEM = "B1257475225120N00105395WA007900085200210";
  const prog_char IGC_LINE_037[] PROGMEM = "B1257515225085N00105482WA007970085700210";
#endif

When I compile this I get

Binary sketch size: 128414 bytes (of a 258048 byte maximum)

So I've saved myself a massive 6 bytes!

Is this because the compiler can't add up? or does it check if the strings actually get used in the project anywhere before attempting to allocate space? (all the strings in the above example I stopped using ages ago, but was too lazy to remove at the time)

At the moment I have a single file that I put all my PROGMEM declarations in, and I include this one file in ALL of my projects. To save compile space in my largest project I was thinking of removing all the irrelevant stuff, but if the compiler is already checking if each string is used, then I guess this isn't going to make any difference?

Cheers

PROGMEM directives save copying your data from program memory (the sketch memory) into RAM at startup. So the data is always there, using PROGMEM saves it also taking RAM.

There are known problems with the Mega and large arrays, I don't recall the thread, but try searching for it.

As for saving memory, the compiler optimizes away stuff you don't use, so your #ifdef doesn't achieve much.

Thanks Nick, i was thinking it was something like that.

cheers

That explains why removing the variable definitions didn’t achieve any substantial difference, but I’m left wondering why it made any difference at all, if this was the only change.

if this was the only change.

it was

This test sketch compiles to 666 bytes (which in itself is kinda creepy):

void setup ()
  {

  }  // end of setup

void loop ()
  {
    
  }  // end of loop
  
  
#undef WASTE_OF_SPACE
#ifdef WASTE_OF_SPACE
  const prog_char IGC_LINE_001[] PROGMEM = "B1255275225709N00105715WA006780074700309";
  const prog_char IGC_LINE_002[] PROGMEM = "B1255315225644N00105791WA006750074500310";
  const prog_char IGC_LINE_003[] PROGMEM = "B1255355225559N00105822WA006780074300310";
  const prog_char IGC_LINE_004[] PROGMEM = "B1255395225479N00105779WA006830074900310";
  const prog_char IGC_LINE_005[] PROGMEM = "B1255435225439N00105682WA006830074900210";
  const prog_char IGC_LINE_006[] PROGMEM = "B1255475225453N00105595WA006830074600210";
  const prog_char IGC_LINE_007[] PROGMEM = "B1255515225496N00105563WA006860074900211";
  const prog_char IGC_LINE_008[] PROGMEM = "B1255555225538N00105554WA006870075200211";
  const prog_char IGC_LINE_009[] PROGMEM = "B1255595225567N00105615WA006900075300210";
  const prog_char IGC_LINE_010[] PROGMEM = "B1256035225535N00105703WA006940075900210";
  const prog_char IGC_LINE_011[] PROGMEM = "B1256075225455N00105720WA006950076000210";
  const prog_char IGC_LINE_012[] PROGMEM = "B1256115225389N00105648WA006950076000209";
  const prog_char IGC_LINE_013[] PROGMEM = "B1256155225372N00105548WA007050076800211";
  const prog_char IGC_LINE_014[] PROGMEM = "B1256195225398N00105485WA007010076800210";
  const prog_char IGC_LINE_015[] PROGMEM = "B1256235225440N00105489WA007010076300211";
  const prog_char IGC_LINE_016[] PROGMEM = "B1256275225465N00105556WA007070076900211";
  const prog_char IGC_LINE_017[] PROGMEM = "B1256315225439N00105646WA007140077600211";
  const prog_char IGC_LINE_018[] PROGMEM = "B1256355225365N00105678WA007210078600211";
  const prog_char IGC_LINE_019[] PROGMEM = "B1256395225297N00105611WA007210078600210";
  const prog_char IGC_LINE_020[] PROGMEM = "B1256435225280N00105510WA007290079100211";
  const prog_char IGC_LINE_021[] PROGMEM = "B1256475225307N00105448WA007290079400210";
  const prog_char IGC_LINE_022[] PROGMEM = "B1256515225347N00105460WA007350079700211";
  const prog_char IGC_LINE_023[] PROGMEM = "B1256555225358N00105534WA007420080400210";
  const prog_char IGC_LINE_024[] PROGMEM = "B1256595225312N00105608WA007470081200209";
  const prog_char IGC_LINE_025[] PROGMEM = "B1257035225233N00105607WA007540081500211";
  const prog_char IGC_LINE_026[] PROGMEM = "B1257075225173N00105528WA007550081900210";
  const prog_char IGC_LINE_027[] PROGMEM = "B1257115225168N00105427WA007530081700211";
  const prog_char IGC_LINE_028[] PROGMEM = "B1257155225209N00105390WA007580081900211";
  const prog_char IGC_LINE_029[] PROGMEM = "B1257195225241N00105441WA007620082500210";
  const prog_char IGC_LINE_030[] PROGMEM = "B1257235225219N00105536WA007690082900210";
  const prog_char IGC_LINE_031[] PROGMEM = "B1257275225145N00105573WA007740083400210";
  const prog_char IGC_LINE_032[] PROGMEM = "B1257315225072N00105520WA007830084300210";
  const prog_char IGC_LINE_033[] PROGMEM = "B1257355225038N00105419WA007810084300211";
  const prog_char IGC_LINE_034[] PROGMEM = "B1257395225056N00105335WA007820084300209";
  const prog_char IGC_LINE_035[] PROGMEM = "B1257435225099N00105328WA007880084900211";
  const prog_char IGC_LINE_036[] PROGMEM = "B1257475225120N00105395WA007900085200210";
  const prog_char IGC_LINE_037[] PROGMEM = "B1257515225085N00105482WA007970085700210";
#endif

I get 666 bytes whether or not WASTE_OF_SPACE is defined.

Binary sketch size: 666 bytes (of a 258,048 byte maximum)

I get 666 bytes whether or not WASTE_OF_SPACE is defined.

I assume this is because the compiler is smart enough to spot that none of the character arrays ever used, so it bins them before it even starts.