Skip to content

Conversation

@willmmiles
Copy link
Member

The switch-case code architecture was placing the timezone specifications in RAM. Move them to PROGMEM, saving ~200 bytes.

Also includes a small patch to move a couple settings strings to PROGMEM, too.

Copy link
Contributor

@blazoncek blazoncek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works like charm and does what it says! 😄
The two strings I commented do not need flash storage as they are used elsewhere. I'd like them reverted though.

wled00/set.cpp Outdated
bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
{
if (!(req.indexOf("win") >= 0)) return false;
if (!(req.indexOf(F("win")) >= 0)) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is unnecessary as "win" is also used elsewhere and AFAIK same strings only occupy space once if not stored in PROGMEM.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's true that string literals can be deduplicated by the linker, while PROGMEM arrays have to be deduplicated by the programmer. Unfortunately, our ESP8266 RAM is basically filled with them. I'll see if I can get some metrics, but we're looking at many kb in total. Browsing the RAM layout, it's just page after page after page of static strings, almost all of which could be in PROGMEM if the surrounding code supported it.

I've got a note in my todo to look at this from a more systematic perspective - I want to prod C++11 user-defined literals and the linker scripts - but I don't think I'll get to that for a while. For the forseeable future, about the only option we have is to go through literal by literal and move everything we can, one patch at a time.

In any event, I'll drop 4c49241 from the PR, and we can consider that process elsewhere.

wled00/set.cpp Outdated
if (subObj[name].isNull()) {
// the first occurrence of the field describes the parameter type (used in next loop)
if (value == "false") subObj[name] = false; // checkboxes may have only one field
if (value == F("false")) subObj[name] = false; // checkboxes may have only one field
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with this one.

@softhack007
Copy link
Member

Just to complement the picture, here are the "savings" on esp32

  • [env:esp32dev] RAM +288 bytes, FLASH +100 bytes
  • [env:esp32dev_V4_dio80] RAM +272 bytes, FLASH -28 bytes

For this PR, we only have a small increase of both RAM and FLASH size, but saving nothing on esp32.

Current stats for [env:esp32dev_V4_dio80] buildenv:
RAM: [=== ] 26.9% (used 87996 bytes from 327680 bytes)
Flash: [========= ] 92.6% (used 1456269 bytes from 1572864 bytes)

My conclusion is that - in contrast to this statement - "progmem-fu" exercises are sometimes harmful on esp32.

It looks like while trying to optimize for 8266, we are filling up flash on esp32, without any added value for esp32 users?

@blazoncek
Copy link
Contributor

It looks like while trying to optimize for 8266, we are filling up flash on esp32, without any added value for esp32 users?

Yes. That's the point, ESP8266 needs every byte of RAM possible.

@willmmiles
Copy link
Member Author

[env:esp32dev] RAM +288 bytes, FLASH +100 bytes

Wow, I didn't check these metrics - I'm very surprised! I'll review the compiler output and see why that's the case. A fixed table shouldn't be any larger than inline constructors. Possibly there's alignment issues, I'll report back with what I find.

@softhack007
Copy link
Member

softhack007 commented Feb 19, 2024

Possibly there's alignment issues

Yes this was my first thought, too. it could also be related to differences in compiler/linker optimizations - esp32 uses function-based unused code removal (-ffunction-sections -fdata-sections and --gc-sections), while 8266 relies on link-time optimization (-flto). I've tried to build esp32 with -flto some time ago - it does reduce flash size, however its also slowing things down, and it puts extra pressure on stack size. So it seems that -flto cannot be the solution for esp32.

@willmmiles
Copy link
Member Author

It turend out to be simpler than that - I just forgot to const the table. How embarassing! The table was already being stored packed. Updated results for my local esp32dev build are 0 RAM, -76 bytes ROM compared to prior to the patch.

Thank you guys for the thorough review.

@blazoncek
Copy link
Contributor

@softhack007 if you agree, please merge. I'll then cherry-pick into main branch.

@softhack007 softhack007 merged commit a28d2c8 into wled:0_15 Feb 20, 2024
@softhack007
Copy link
Member

@softhack007 if you agree, please merge. I'll then cherry-pick into main branch.

I agree - merged :-)

@willmmiles willmmiles deleted the tztable-progmem branch March 7, 2024 00:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants