Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drastic changes in firmware size (IDFGH-1516) #3781

Closed
ammaree opened this issue Jul 15, 2019 · 21 comments
Closed

drastic changes in firmware size (IDFGH-1516) #3781

ammaree opened this issue Jul 15, 2019 · 21 comments
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally

Comments

@ammaree
Copy link

ammaree commented Jul 15, 2019

After upgrading from the previous master (as of 6 July) to current master (as of 13 July) the size of my firmware has increased from 970,512 to 981,952 (about 11KB) without ANY CHANGE in the application.

Is there anywhere in the system documentation where such changes are listed, alternatively is there an automated method whereby the modules and/or functions responsible can be identified?

A change of a couple of hundred byte or maybe a KB or 2 can be ignored but >10KB in 1 week sounds very rough.

@github-actions github-actions bot changed the title drastic changes in firmware size drastic changes in firmware size (IDFGH-1516) Jul 15, 2019
@projectgus
Copy link
Contributor

Hi @ammaree ,

Agree that 10KB is a large amount of binary size shift. A have two questions so we can help narrow this down:

  • Do you know the git commit SHAs for IDF that you were using before/after updating?

  • Is it possible for you to please give the output of idf.py size-components (or make size-components, as applicable) for your project before & after? This will help us see which components you are using in your app, and which are contributing to the binary size.

@ammaree
Copy link
Author

ammaree commented Jul 16, 2019

Hi @projectgus

Git commit SHA after updating is the latest fdab15d
Git commit SHA before is difficult to say, I think around 783ddd1

Getting the size components on the before application might be a bit difficult unless I:
a) revert to that version of the IDF; and
b) revert the the changes made to our application

I have attached the after "size-components" file. If you can tell me how to revert to the "before" status I will do so and rebuild.
size-components after update.txt

@negativekelvin
Copy link
Contributor

without ANY CHANGE in the application

b) revert the the changes made to our application

?

@igrr
Copy link
Member

igrr commented Jul 16, 2019

To revert to an earlier version, you can do git checkout <commit-id> (783ddd1 for IDF as you have mentioned). Don't forget to run git submodule update --init afterwards.

@ammaree
Copy link
Author

ammaree commented Jul 16, 2019

@negativekelvin

When problem was discovered and originally logged, no changed had been made to our application.

24 hours later some changes had been made hence not a completely simple process to revert to the state yesterday.

@negativekelvin
Copy link
Contributor

Ok but if idf is responsible for the 10k it shouldn't be dependent on your app so as long as it builds on the older idf you should be able to compare

@ammaree
Copy link
Author

ammaree commented Jul 16, 2019

Correct, will rebuild both and hopefully see same/similar difference

@ammaree
Copy link
Author

ammaree commented Jul 16, 2019

Have done, new before and after sizes attached.
Primary movers are 3 modules with change >1KB
libmbedtls +2406 bytes
liblwip +14820 bytes
libphy -3702 bytes
size-components before.txt
size-components after update.txt

@projectgus
Copy link
Contributor

projectgus commented Jul 17, 2019

Thanks for the info @ammaree .

We've updated both mbedTLS and LWIP versions in between the two commits you're using.

  • For mbedTLS, we also changed the way default config is generated so there may be some features which weren't enabled before but now are. Will check.
  • For LWIP the difference in size is more pronounced, unsure what the root cause is. We'll look into this also.

@mahavirj
Copy link
Member

@ammaree Is it possible to share your sdkconfig file (from example build)?

@ammaree
Copy link
Author

ammaree commented Jul 23, 2019

@mahavirj

If you want the exact SDK for the "before" or "after" build, might be a bit difficult.
The attached sdkconfig file is for the application as it currently stands, but the only items changed relate to log levels, nothing to do with LwIP.

File extention was changed to allow attaching. Hope this helps

sdkconfig.txt

@projectgus
Copy link
Contributor

projectgus commented Aug 1, 2019

Hi @ammaree ,

A short update on this:

For mbedTLS, it looks like most of the increase is from our default/recommended config in the new version so we can't change this part automatically. However if you want to save code size from mbedTLS, there are a number of options you can disable in the project config to make substantial reductions - for example removing ciphersuites that you don't intend to use.

For LWIP, most of the increase is from new IPV6 related features added in LWIP 2.1.2. We're currently testing which of these features can have config options to disable them, without causing problems in other supported functionality. We may also offer the option to disable IPV6 entirely, which would save significant binary size if not needed, but this requires additional testing again.

@ammaree
Copy link
Author

ammaree commented Aug 1, 2019

@projectgus

LwIP: The option to disable IPv6 would be superb. Considering that our service and device are contained to a very small ecosystem, and that the use of IPv6 within our ecosystem is currently ~0% this will buy us significant time

MbedTLS: Our current ESP32 device communicates via HTTPS and MQTT(s) to our own cloud service hence we have complete control of both sides. The only external (to our eco system) communications is between devices and Google Maps API's to do geolocation and TZ determination, on a very irregular basis.

Some advice from yourselves (or anyone in the community) to choose the optimal cipher suite providing the best balance of speed and size (whilst accommodating Google API requirements) would be of great value.

@AshUK
Copy link
Contributor

AshUK commented Apr 23, 2021

+1 would also like to disable IPv6

Currently disabling IPv6 (CONFIG_LWIP_IPV6) results in a failing build on latest master (cf457d4)

@igrr
Copy link
Member

igrr commented Apr 23, 2021

@AshUK could you please open a new issue for this, attaching the build log and your sdkconfig file?
I see that we are testing that examples/protocols/sockets/tcp_server example can be built with CONFIG_LWIP_IPV6=n in our CI, and the test seems to be passing.

@AshUK
Copy link
Contributor

AshUK commented Apr 23, 2021

@igrr sorry should have been clearer.

By disabling coap and asio components i.e adding the following to the root CMakeLists.txt set(EXCLUDE_COMPONENTS "coap" "asio") resolves the build issue when disabling IPv6. Removing the COAP component makes sense as the protocol uses IPv6 addressing as part of the specification. I cannot speak for the ESP-ASIO component as to why it requires IPv6.

Our project makes no use of the COAP or ESP-ASIO component. So not sure why it built by default. Happy to open a new issue if this is actually an unintended consequence, but i would say its not worthy of time investigating.

Apologies for polluting this thread.

@igrr
Copy link
Member

igrr commented Apr 23, 2021

Thanks for explanation, and my bad — I didn't realize the example was disabling coap and asio. Now I remember that indeed these two components haven't been yet been adapted to CONFIG_LWIP_IPV6 (e.g. by automatically disabling them).

Our project makes no use of the COAP or ESP-ASIO component. So not sure why it built by default.

The default behavior of ESP-IDF build system (added for compatibility with the legacy Make based build system) is to build all components in IDF and in the project. The unused components are then eliminated by the linker. It is typically slower than building just the things that are needed, but we decided to do it this way because:

  1. This matched the behavior of the Make based build system in IDF 3.x, so migration to CMake would be less cumbersome.
  2. By default, developers wouldn't need to worry about component dependencies, as all components would be available and main implicitly depends on all components (unless you specify REQUIRES or PRIV_REQUIRES in idf_component_register). So, lower learning curve.
  3. It is still possible to trim the build to improve build times later during development.

We understand that it is now hard to change this default behaviour since so many projects rely on it, but I'm not going to digress further :)

I mentioned above that it is possible to trim down the list of components included in the build. The "Build System" documentation page in IDF Programming Guide describes this, but here is the idea in a nutshell:

  1. Set the COMPONENTS variable in the project CMakeLists.txt file: set(COMPONENTS esptool_py main). Here, esptool_py is needed because of a quirk in the build system, it might not be necessary on master branch but is probably needed for released versions. main is assumed to be the main component of your app.
  2. In main component, specify requirements on other components it depends on, for example:
    idf_component_register(SRCS "main.c"
                        INCLUDE_DIRS "."
                        REQUIRES nvs_flash wifi_provisioning my_extra_component)

As the result, the build system will determine the component dependencies, and will only include the components required + all their recursive dependencies + "common" components (which are always built, like esp_common, esp_system, bootloader, etc). The list of "common" components is not small at the moment, but you will still see improvement in build time once you declare the dependencies this way.

To make it clear to anyone who will be reading this later, trimming down the build this way generally doesn't result in any size reduction of the final app (the topic of this ticket). The linker is already doing as much as possible in removing unused code at link time, and removing unused components from the build will not cause any difference for the code size.

@AxelLin
Copy link
Contributor

AxelLin commented Apr 24, 2021

I tried adding set(EXCLUDE_COMPONENTS "coap" "asio") in CMakeLists.txt,
but I got below build error for my application: (if with CONFIG_LWIP_IPV6=n )

/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c: In function 'on_ppp_status_changed':
/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c:76:54: error: 'ip_addr_t' {aka 'struct ip4_addr'} has no member named 'u_addr'; did you mean 'addr'?
                 evt.ip_info.ip.addr = pppif->ip_addr.u_addr.ip4.addr;
                                                      ^~~~~~
                                                      addr
/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c:77:49: error: 'ip_addr_t' {aka 'struct ip4_addr'} has no member named 'u_addr'; did you mean 'addr'?
                 evt.ip_info.gw.addr = pppif->gw.u_addr.ip4.addr;
                                                 ^~~~~~
                                                 addr
/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c:78:59: error: 'ip_addr_t' {aka 'struct ip4_addr'} has no member named 'u_addr'; did you mean 'addr'?
                 evt.ip_info.netmask.addr = pppif->netmask.u_addr.ip4.addr;
                                                           ^~~~~~
                                                           addr
/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c:82:43: error: 'ip_addr_t' {aka 'const struct ip4_addr'} has no member named 'u_addr'; did you mean 'addr'?
                     ns1.addr = (*dest_ip).u_addr.ip4.addr;
                                           ^~~~~~
                                           addr
/home/axel/esp/esp-idf/components/esp_netif/lwip/esp_netif_lwip_ppp.c:86:43: error: 'ip_addr_t' {aka 'const struct ip4_addr'} has no member named 'u_addr'; did you mean 'addr'?
                     ns2.addr = (*dest_ip).u_addr.ip4.addr;
                                           ^~~~~~
                                           addr

@igrr
Copy link
Member

igrr commented Apr 25, 2021

@AxelLin My guess is that we aren't testing the combination of CONFIG_LWIP_PPP_SUPPORT=y and CONFIG_LWIP_IPV6=n, and it isn't working. Would you mind opening a new issue about this, preferably attaching your sdkconfig and mentioning the IDF version?

@AxelLin
Copy link
Contributor

AxelLin commented Apr 26, 2021

Just to share:

  1. CONFIG_LWIP_PPP_SUPPORT=y && CONFIG_LWIP_IPV6=n actually works after fixing the build failure
  2. My firmware size reduces about 32KB after setting CONFIG_LWIP_IPV6=n.
CONFIG_LWIP_IPV6=n:
            Archive File DRAM .data & .bss & other   IRAM   D/IRAM Flash code & rodata   Total
               liblwip.a         17   2814       0      0        0     106727    22822  132380

CONFIG_LWIP_IPV6=y:
            Archive File DRAM .data & .bss & other   IRAM   D/IRAM Flash code & rodata   Total
               liblwip.a         25   4753       0      0        0     136089    24525  165392

@projectgus
Copy link
Contributor

Regarding the LWIP_IPV6 issue, a change to remove the need to manually disable components is in review.

Regarding binary size, a new Performance Guide section soon will be added to ESP-IDF Programming Guide soon that includes steps for analyzing binary size and tips for reducing it. This issue will be updated when that guide has merged.

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally labels Jun 4, 2021
espressif-bot pushed a commit that referenced this issue Jun 6, 2021
… coap

- Removes need to manually exclude these components as shown at
  #3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files
espressif-bot pushed a commit that referenced this issue Nov 24, 2021
… coap

- Removes need to manually exclude these components as shown at
  #3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files

Backport of e305f29

Closes #7816
gabsuren pushed a commit to gabsuren/esp-protocols-1 that referenced this issue May 28, 2022
… coap

- Removes need to manually exclude these components as shown at
  espressif/esp-idf#3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files


* Original commit: espressif/esp-idf@e305f29
gabsuren pushed a commit to gabsuren/esp-protocols-1 that referenced this issue Jun 3, 2022
… coap

- Removes need to manually exclude these components as shown at
  espressif/esp-idf#3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files


* Original commit: espressif/esp-idf@e305f29
gabsuren pushed a commit to gabsuren/esp-protocols-1 that referenced this issue Jun 22, 2022
… coap

- Removes need to manually exclude these components as shown at
  espressif/esp-idf#3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files


* Original commit: espressif/esp-idf@e305f29
euripedesrocha pushed a commit to euripedesrocha/esp-protocols that referenced this issue Oct 17, 2022
… coap

- Removes need to manually exclude these components as shown at
  espressif/esp-idf#3781 (comment)

- Hide the config for these components if IPV6 is disabled

- The components are still included in the build, but with no source
  files


* Original commit: espressif/esp-idf@e305f29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally
Projects
None yet
Development

No branches or pull requests

8 participants