IRremoteESP8266
IRremoteESP8266 copied to clipboard
In search for RAM to save, why use ints instead of defines?
In my endless quest to save RAM in my project (ESPEasy) I came across this section of the code:
https://github.com/crankyoldgit/IRremoteESP8266/blob/85d587fbbf804c25c15632849386091e712a6cae/src/IRremoteESP8266.h#L1112-L1388
These are all const uint16_t and I wonder why these need to be C++ objects instead of defines.
As objects they take RAM, where as defines they are just numbers in the code.
So I was wondering, is there a specific reason for having them as an object? If not, would you appreciate a PR to convert these? I have not tried it yet, but my guess is that it would save roughly 550 bytes of RAM and maybe also reduce the build size slightly as a bonus.
You are under the impression that these takes RAM? Do you have anything that shows that is the case?
There is explanations on why DEFINE is not used and should be avoided. As well as previous issues on this same topic.
(I will add references to these in a bit)
I believe we have tried this before.
Please see the rest of #1493 for other efforts we've tried.
So I was wondering, is there a specific reason for having them as an object?
Yes, there is. As defined contants vs. defines, you're able to do type checking on them. It is also part of the style guide we use. They are not really in an object per se. Well, not as I understand it. The compiler does the right thing. They are not included if they are not used, and the don't take up SRAM.
If not, would you appreciate a PR to convert these?
Feel free to. If it can be proven to save space, I'll certainly look into it. But please see https://github.com/crankyoldgit/IRremoteESP8266/issues/1493#issuecomment-900232738 before you try/waste effort on it.
I have not tried it yet, but my guess is that it would save roughly 550 bytes of RAM and maybe also reduce the build size slightly as a bonus.
I suggest you try for yourself, but I've already tried similar and it didn't save anything.
But as I said, prove it works and I'll be all on it.
So after that (much better explanation then mine) I will now propose we close this. But are totally ready to reopen, if numbers can be shown that this would make any difference.
Thanks for the links. I will have a look at the previous attempts. One of my users is already doing some quick preliminary tests to see if it indeed saves RAM. I will get back to this.
I'll add (to be clear on what we expect) if built with debug flags enabled it might have an impact (but we won't optimize that)
However in general, builds are not and these consts are optimized and you would not see any difference. But if it does make a difference do consider it a bug in the compiler, or the build settings/parameters. But of course it is great to have such cases documented.
Thanks for the links. I will have a look at the previous attempts. One of my users is already doing some quick preliminary tests to see if it indeed saves RAM.
I wish them well. I'm fairly sure the values are treated as literals & stored in Flash/progmem space. So, if it does reduce, it will most likely be in flash/progmem space, not RAM (on an ESP8266).
If you look at those links and the comments from @mcspr . They point out how to use the gdb to look at the actual instructions built/compiled and it can determine where a variable or constant is located. i.e. Ram or Flash.
It's been a while since I delved into it. But if I recall correctly, I looked into it and the consts were all stored in Flash space.
e.g.
blah += kConstant; with gdb, when looking at the addresses in use in the compiled binary, kConstant was located in Flash/ProgMem, and most def. not a variable in RAM. Same as using the code: blah += 4; etc. The 4 is stored in Flash/Progmem.
But hey, it's been a while. I could be remembering wrong and/or things have changed etc.
+1 to 'gdb'. Here it is useful as an interactive 'objdump', 'nm', 'readelf', etc. all in the same box.
And on case-by-case basis (...preferably, not to go cross-eyed...). Compiler sees the whole code, then optimizer and then the linker get their pass at the code. inlineness, constexpr'ness also matters, or whether it is a symbol shared between files.
You may also run into the case where value is inserted as part of the machine code.
(see disassemble /m <func> and disassemble /r <func>. we just had a set of patches to the xtensa toolchain that sometimes do that)
Another one is C++ is not C, rules may vary between the two when dealing with 'const'ants and 'constexpr'essions. (e.g. I love the very first example from this c23 blog post :)
Interesting blogpost!
OK, got feedback from this user with an already predicted result... It doesn't reduce RAM usage and even causes some (small) increase in build size.
So this can be closed.
even causes some (small) increase in build size.
Okay, that was an unexpected result. Thanks for the confirmation.