diff --git a/docs/en/api-guides/performance/size.rst b/docs/en/api-guides/performance/size.rst index b38a2b7d1e..f88f8a38bc 100644 --- a/docs/en/api-guides/performance/size.rst +++ b/docs/en/api-guides/performance/size.rst @@ -3,8 +3,6 @@ Minimizing Binary Size :link_to_translation:`zh_CN:[中文]` -{IDF_TARGET_REDUCED_BY_IRAM: default="DRAM", esp32="IRAM and/or DRAM (depending on sizes)"} - The ESP-IDF build system compiles all source files in the project and ESP-IDF, but only functions and variables that are actually referenced by the program are linked into the final binary. In some cases, it is necessary to reduce the total size of the firmware binary, e.g., in order to fit it into the available flash partition size. The first step to reducing the total firmware binary size is measuring what is causing the size to increase. @@ -14,312 +12,12 @@ The first step to reducing the total firmware binary size is measuring what is c Measuring Static Sizes ---------------------- -To optimize both the firmware binary size and the memory usage, it is necessary to measure statically-allocated RAM (``data``, ``bss``), code (``text``), and read-only data (``rodata``) in your project. - -Using the :ref:`idf.py` sub-commands ``size``, ``size-components``, and ``size-files`` provides a summary of memory used by the project: - -.. note:: - - It is possible to add ``-DOUTPUT_FORMAT=csv`` or ``-DOUTPUT_FORMAT=json`` to get the output in CSV or JSON format. - -Size Summary ``idf.py size`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. only:: esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used static DRAM: 10608 bytes ( 170128 remain, 5.9% used) - .data size: 8464 bytes - .bss size: 2144 bytes - Used static IRAM: 48834 bytes ( 82238 remain, 37.3% used) - .text size: 47807 bytes - .vectors size: 1027 bytes - Used Flash size : 117391 bytes - .text: 80103 bytes - .rodata: 37032 bytes - Total image size: 174689 bytes (.bin may be padded larger) - - -.. only:: not esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used stat D/IRAM: 53743 bytes ( 122385 remain, 30.5% used) - .data size: 6504 bytes - .bss size: 1984 bytes - .text size: 44228 bytes - .vectors size: 1027 bytes - Used Flash size : 118879 bytes - .text: 83467 bytes - .rodata: 35156 bytes - Total image size: 170638 bytes (.bin may be padded larger) - -This output breaks down the size of all static memory regions in the firmware binary: - -.. only:: esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used static DRAM: 10608 bytes ( 170128 remain, 5.9% used) - .data size: 8464 bytes - .bss size: 2144 bytes - Used static IRAM: 48834 bytes ( 82238 remain, 37.3% used) - .text size: 47807 bytes - .vectors size: 1027 bytes - Used Flash size : 117391 bytes - .text: 80103 bytes - .rodata: 37032 bytes - Total image size: 174689 bytes (.bin may be padded larger) - - - ``Used static DRAM``: Total amount of DRAM allocated at compile time. ``remain`` indicates the amount of DRAM left to be used as heap memory at runtime. Note that due to meta data overhead, implementation constraints, and startup heap allocations, the actual size of the DRAM heap is smaller. - - - ``.data size``: Amount of DRAM allocated at compile time for the ``.data`` (i.e., all statically allocated variables that are initialized to non-zero values). ``.data`` also consumes space in the binary image to store the non-zero initialization values. - - ``.bss size``: Amount of DRAM allocated at compile time for ``.bss`` (i.e., all statically allocated variables that are initialized to zero). ``.bss`` does not consume extra space in flash. - - - ``Used static IRAM``: Total amount of IRAM allocated at compile time. ``remain`` indicates the amount of IRAM left to be used as heap memory at runtime. Note that due to meta data overhead, implementation constraints, and startup heap allocations, the actual size of the IRAM heap is smaller. - - - ``.text size``: Amount of IRAM used for ``.text`` (i.e., all code that is executed from :ref:`IRAM `). ``.text`` also consumes space in the binary image as the code is initially stored there and is then copied over to IRAM on startup. - - - ``Used Flash size``: Total amount of flash used (excluding usage by DRAM and IRAM) - - - ``.text``: Amount of flash used for ``.text`` (i.e., all code that is executed via the flash cache, see :ref:`IROM `). - - ``.rodata``: Amount of flash used for ``.rodata`` (i.e., read-only data that is loaded via the flash cache, see :ref:`DROM `). - - - ``Total image size`` is the estimated total size of the binary file. - -.. only:: not esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used stat D/IRAM: 53743 bytes ( 122385 remain, 30.5% used) - .data size: 6504 bytes - .bss size: 1984 bytes - .text size: 44228 bytes - .vectors size: 1027 bytes - Used Flash size : 118879 bytes - .text: 83467 bytes - .rodata: 35156 bytes - Total image size: 170638 bytes (.bin may be padded larger) - - - ``Used stat D/IRAM``: Total amount of D/IRAM used at compile time. ``remain`` indicates the amount of D/IRAM left to be used as heap memory at runtime. Note that due to meta data overhead, implementation constraints, and startup heap allocations, the actual size of the DRAM heap is smaller. - - - ``.data size``: Amount of D/IRAM allocated at compile time for the ``.data`` (i.e., all statically allocated variables that are initialized to non-zero values). ``.data`` also consumes space in the binary image to store the non-zero initialization values. - - ``.bss size``: Amount of D/IRAM allocated at compile time for ``.bss`` (i.e., all statically allocated variables that are initialized to zero). ``.bss`` does not consume extra space in flash. - - ``.text size``: Amount of D/IRAM used for ``.text`` (i.e., all code that is executed from internal RAM). ``.text`` also consumes space in the binary image as the code is initially stored there and is then copied over to D/IRAM on startup. - - - ``Used Flash size``: Total amount of flash used (excluding usage by D/IRAM) - - - ``.text``: Amount of flash used for ``.text`` (i.e., all code that is executed via the flash cache, see :ref:`IROM `). - - ``.rodata``: Amount of flash used for ``.rodata`` (i.e., read-only data that is loaded via the flash cache, see :ref:`DROM `). - - - ``Total image size`` is the estimated total size of the binary file. - - -Component Usage Summary ``idf.py size-components`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The summary output provided by ``idf.py size`` does not give enough details to find the main contributor to excessive binary size. To analyze in detail, use ``idf.py size-components``. - -.. code-block:: bash - - $ idf.py size-components - [...] - Total sizes: - DRAM .data size: 14956 bytes - DRAM .bss size: 15808 bytes - Used static DRAM: 30764 bytes ( 149972 available, 17.0% used) - Used static IRAM: 83918 bytes ( 47154 available, 64.0% used) - Flash code: 559943 bytes - Flash rodata: 176736 bytes - Total image size:~ 835553 bytes (.bin may be padded larger) - Per-archive contributions to ELF file: - Archive File DRAM .data & .bss & other IRAM D/IRAM Flash code & rodata Total - libnet80211.a 1267 6044 0 5490 0 107445 18484 138730 - liblwip.a 21 3838 0 0 0 97465 16116 117440 - libmbedtls.a 60 524 0 0 0 27655 69907 98146 - libmbedcrypto.a 64 81 0 30 0 76645 11661 88481 - libpp.a 2427 1292 0 20851 0 37208 4708 66486 - libc.a 4 0 0 0 0 57056 6455 63515 - libphy.a 1439 715 0 7798 0 33074 0 43026 - libwpa_supplicant.a 12 848 0 0 0 35505 1446 37811 - libfreertos.a 3104 740 0 15711 0 367 4228 24150 - libnvs_flash.a 0 24 0 0 0 14347 2924 17295 - libspi_flash.a 1562 294 0 8851 0 1840 1913 14460 - libesp_system.a 245 206 0 3078 0 5990 3817 13336 - libesp-tls.a 0 4 0 0 0 5637 3524 9165 - [... removed some lines here ...] - libesp_rom.a 0 0 0 112 0 0 0 112 - libcxx.a 0 0 0 0 0 47 0 47 - (exe) 0 0 0 3 0 3 12 18 - libesp_pm.a 0 0 0 0 0 8 0 8 - libesp_eth.a 0 0 0 0 0 0 0 0 - libmesh.a 0 0 0 0 0 0 0 0 - -The first lines of the output from ``idf.py size-components`` are the same as that from ``idf.py size``. After this, a table is printed as ``Per-archive contributions to ELF file``. This means how much each static library archive has contributed to the final binary size. - -Generally, one static library archive is built per component, although some are binary libraries included by a particular component, for example, ``libnet80211.a`` is included by ``esp_wifi`` component. There are also toolchain libraries such as ``libc.a`` and ``libgcc.a`` listed here, these provide Standard C/C++ Library and toolchain built-in functionality. - -If your project is simple and only has a ``main`` component, then all of the project's code will be shown under ``libmain.a``. If your project includes its own components (see :doc:`/api-guides/build-system`), then they will each be shown on a separate line. - -The table is sorted in descending order of the total contribution of the static archive to the binary size. - -The columns are as follows: - -.. list:: - - - ``DRAM .data & .bss & other`` - ``.data`` and ``.bss`` are the same as for the totals shown above. Both are static variables and reduce the total available RAM at runtime, but ``.bss`` does not contribute to the binary file size. ``other`` is a column for any custom section types that also contribute to RAM size. Usually, the value is 0. - :esp32: - ``IRAM`` - is the same as for the totals shown above. It refers to code linked to execute from IRAM, which uses space in the binary file and also reduces IRAM that can be dynamically allocated at runtime using ``HEAP_CAP_32BIT``. - :esp32: - ``D/IRAM`` - shows IRAM space which, due to occupying D/IRAM space, is also reducing available DRAM available as heap at runtime. - :not esp32: - ``IRAM`` - is the same as for the totals shown above. It refers to code linked to execute from IRAM, which uses space in the binary file and also reduces DRAM available as heap at runtime. - - ``Flash code & rodata`` - these are the same as the totals above, IROM and DROM space accessed from the flash cache that contribute to the binary size. - -Source File Usage Summary ``idf.py size-files`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For even more details, run ``idf.py size-files`` to get a summary of the contribution each object file has made to the final binary size. Each object file corresponds to a single source file. - -.. code-block:: bash - - $ idf.py size-files - [...] - Total sizes: - DRAM .data size: 14956 bytes - DRAM .bss size: 15808 bytes - Used static DRAM: 30764 bytes ( 149972 available, 17.0% used) - Used static IRAM: 83918 bytes ( 47154 available, 64.0% used) - Flash code: 559943 bytes - Flash rodata: 176736 bytes - Total image size:~ 835553 bytes (.bin may be padded larger) - Per-file contributions to ELF file: - Object File DRAM .data & .bss & other IRAM D/IRAM Flash code & rodata Total - x509_crt_bundle.S.o 0 0 0 0 0 0 64212 64212 - wl_cnx.o 2 3183 0 221 0 13119 3286 19811 - phy_chip_v7.o 721 614 0 1642 0 16820 0 19797 - ieee80211_ioctl.o 740 96 0 437 0 15325 2627 19225 - pp.o 1142 45 0 8871 0 5030 537 15625 - ieee80211_output.o 2 20 0 2118 0 11617 914 14671 - ieee80211_sta.o 1 41 0 1498 0 10858 2218 14616 - lib_a-vfprintf.o 0 0 0 0 0 13829 752 14581 - lib_a-svfprintf.o 0 0 0 0 0 13251 752 14003 - ssl_tls.c.o 60 0 0 0 0 12769 463 13292 - sockets.c.o 0 648 0 0 0 11096 1030 12774 - nd6.c.o 8 932 0 0 0 11515 314 12769 - phy_chip_v7_cal.o 477 53 0 3499 0 8561 0 12590 - pm.o 32 364 0 2673 0 7788 782 11639 - ieee80211_scan.o 18 288 0 0 0 8889 1921 11116 - lib_a-svfiprintf.o 0 0 0 0 0 9654 1206 10860 - lib_a-vfiprintf.o 0 0 0 0 0 10069 734 10803 - ieee80211_ht.o 0 4 0 1186 0 8628 898 10716 - phy_chip_v7_ana.o 241 48 0 2657 0 7677 0 10623 - bignum.c.o 0 4 0 0 0 9652 752 10408 - tcp_in.c.o 0 52 0 0 0 8750 1282 10084 - trc.o 664 88 0 1726 0 6245 1108 9831 - tasks.c.o 8 704 0 7594 0 0 1475 9781 - ecp_curves.c.o 28 0 0 0 0 7384 2325 9737 - ecp.c.o 0 64 0 0 0 8864 286 9214 - ieee80211_hostap.o 1 41 0 0 0 8578 585 9205 - wdev.o 121 125 0 4499 0 3684 580 9009 - tcp_out.c.o 0 0 0 0 0 5686 2161 7847 - tcp.c.o 2 26 0 0 0 6161 1617 7806 - ieee80211_input.o 0 0 0 0 0 6797 973 7770 - wpa.c.o 0 656 0 0 0 6828 55 7539 - [... additional lines removed ...] - -After the summary of total sizes, a table of ``Per-file contributions to ELF file`` is printed. - -The columns are the same as shown above for ``idy.py size-components``, but this time the granularity is the contribution of each individual object file to the binary size. - -For example, we can see that the file ``x509_crt_bundle.S.o`` contributed 64,212 bytes to the total firmware size, all as ``.rodata`` in flash. Therefore we can guess that this application is using the :doc:`/api-reference/protocols/esp_crt_bundle` feature and not using this feature would save at last this many bytes from the firmware size. - -Some of the object files are linked from binary libraries and therefore you will not find a corresponding source file. To locate which component a source file belongs to, it is generally possible to search in the ESP-IDF source tree or look in the :ref:`linker-map-file` for the full path. - -Comparing Two Binaries -^^^^^^^^^^^^^^^^^^^^^^ - -If making some changes that affect binary size, it is possible to use an ESP-IDF tool to break down the exact differences in size. - -This operation is not part of ``idf.py``, it is necessary to run the `esp_idf_size `_ Python tool directly. - -To do so, first, locate the linker map file with the name ``PROJECTNAME.map`` in the build directory. The ``esp_idf_size`` tool performs its analysis based on the output of the linker map file. - -To compare with another binary, you also need its corresponding ``.map`` file saved from the build directory. - -For example, to compare two builds, one of which with the default :ref:`CONFIG_COMPILER_OPTIMIZATION` setting ``Debug (-Og)`` configuration while another with ``Optimize for size (-Os)``: - -.. code-block:: bash - - $ python -m esp_idf_size --diff build_Og/https_request.map build_Os/https_request.map - MAP file: build_Os/https_request.map - MAP file: build_Og/https_request.map - Difference is counted as - , i.e. a positive number means that is larger. - Total sizes of : Difference - DRAM .data size: 14516 bytes 14956 -440 - DRAM .bss size: 15792 bytes 15808 -16 - Used static DRAM: 30308 bytes ( 150428 available, 16.8% used) 30764 -456 ( +456 available, +0 total) - Used static IRAM: 78498 bytes ( 52574 available, 59.9% used) 83918 -5420 ( +5420 available, +0 total) - Flash code: 509183 bytes 559943 -50760 - Flash rodata: 170592 bytes 176736 -6144 - Total image size:~ 772789 bytes (.bin may be padded larger) 835553 -62764 - -We can see from the ``Difference`` column that changing this one setting caused the whole binary to be over 60 KB smaller and over 5 KB more RAM is available. - -It is also possible to use the ``diff`` mode to output a table of component-level (static library archive) differences: - -.. note:: - - To get the output in JSON or CSV format using ``esp_idf_size``, it is possible to use the ``--format`` option. - -.. code-block:: bash - - python -m esp_idf_size --archives --diff build_Og/https_request.map build_Oshttps_request.map - -Also at the individual source file level: - -.. code-block:: bash - - python -m esp_idf_size --files --diff build_Og/https_request.map build_Oshttps_request.map - -Other options, like writing the output to a file, are available, pass ``--help`` to see the full list. - -.. _idf-size-linker-failed: - -Showing Size When Linker Fails -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If too much static memory is allocated, the linker will fail with an error such as ``DRAM segment data does not fit``, ``region `iram0_0_seg' overflowed by 44 bytes``, or similar. - -In these cases, ``idf.py size`` will not succeed either. However, it is possible to run ``esp_idf_size`` manually to view the **partial static memory usage**. The memory usage will miss the variables that could not be linked, so there still appears to be some free space. - -The map file argument is ``.map`` in the build directory. - -.. code-block:: bash - - python -m esp_idf_size build/project_name.map - -It is also possible to view the equivalent of ``size-components`` or ``size-files`` output: - -.. code-block:: bash - - python -m esp_idf_size --archives build/project_name.map - python -m esp_idf_size --files build/project_name.map +To optimize both the firmware binary size and the memory usage, it is necessary to measure statically-allocated RAM (``data``, ``bss``), code (``text``), and read-only data (``rodata``) in your project. The :ref:`idf.py` sub-commands ``size``, ``size-components``, and ``size-files`` can be used to examine statically-allocated RAM usage at different levels of detail. For more information, please see the :doc:`/api-guides/tools/idf-size` tool. .. _linker-map-file: Linker Map File -^^^^^^^^^^^^^^^ +--------------- .. note:: diff --git a/docs/en/api-guides/tools/idf-size.rst b/docs/en/api-guides/tools/idf-size.rst new file mode 100644 index 0000000000..d456f5392e --- /dev/null +++ b/docs/en/api-guides/tools/idf-size.rst @@ -0,0 +1,266 @@ +******** +IDF Size +******** + +IDF Size is a tool for analyzing statically-allocated memory in ESP-IDF project. The main functionality is provided by the esp-idf-size_ Python package, while :ref:`idf.py` offers a more user-friendly and higher-level interface through the ``size``, ``size-components``, and ``size-files`` sub-commands. These sub-commands allow you to specify various options, such as the report's output format. For more details, please use the ``--help`` option. ESP-IDF also includes a handy ``idf_size.py`` wrapper to invoke the esp-idf-size_ Python module. For more information, use the command ``idf_size.py --help``. + +Size Summary ``idf.py size`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This output provides a summary of the statically-allocated memory for different memory types in the firmware binary: + +.. code-block:: bash + + $ idf.py size + Memory Type Usage Summary + ┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Memory Type/Section ┃ Used [bytes] ┃ Used [%] ┃ Remain [bytes] ┃ Total [bytes] ┃ + ┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ Flash Code │ 80666 │ 2.41 │ 3261638 │ 3342304 │ + │ .text │ 80666 │ 2.41 │ │ │ + │ IRAM │ 51835 │ 39.55 │ 79237 │ 131072 │ + │ .text │ 50807 │ 38.76 │ │ │ + │ .vectors │ 1027 │ 0.78 │ │ │ + │ Flash Data │ 38224 │ 0.91 │ 4156048 │ 4194272 │ + │ .rodata │ 37968 │ 0.91 │ │ │ + │ .appdesc │ 256 │ 0.01 │ │ │ + │ DRAM │ 11236 │ 6.22 │ 169500 │ 180736 │ + │ .data │ 8988 │ 4.97 │ │ │ + │ .bss │ 2248 │ 1.24 │ │ │ + │ RTC SLOW │ 24 │ 0.29 │ 8168 │ 8192 │ + │ .rtc_slow_reserved │ 24 │ 0.29 │ │ │ + └───────────────────────┴──────────────┴──────────┴────────────────┴───────────────┘ + Total image size: 179712 bytes (.bin may be padded larger) + +Espressif chips include various :doc:`/api-guides/memory-types`, which are detailed in the `Technical Reference Manual (TRM) <{IDF_TARGET_TRM_EN_URL}>`__. These memory types are listed in the ``Memory Type`` column, along with the ELF ``Sections`` that are loaded into each type. The ``Used`` columns display the memory usage for each specific memory type or section. The ``Remain`` column indicates the remaining available memory for the specified memory type. The ``Total`` column shows the total available memory for that memory type, based on the memory region sizes defined in the linker script that map into the memory type. + +.. note:: + + The ``Total`` memory available for each memory type, like ``IRAM``, is determined by the memory region sizes specified in the link map file, which is generated by the linker script, with the MEMORY command, during the build process. The esp-idf-size tool includes YAML files for each target, detailing memory type ranges based on the TRM. The memory ranges from the link map file are mapped to these memory type ranges. This process calculates the total memory available for different memory types. Note that the total available size may differ from what is stated in the TRM, as some memory portions may be reserved for purposes such as the bootloader or cache, depending on the configuration. The remaining memory is calculated by subtracting the sizes of output ``Sections`` loaded to the specific memory type from the ``Total`` size. + +.. note:: + + Certain memory types might map to the same hardware memory. On some targets, ``IRAM`` and ``DRAM`` could be mapped to the same hardware memory but at different virtual addresses, accessible through data and instruction buses. These memory types are referred to as ``DIRAM`` in the ``Memory Type`` column. + +Below is a description of the most interesting memory types and output sections. Please note that all output sections with a non-zero size are included in the summary. Their names are determined by the output section names specified in the linker script. + +- ``DRAM``: Total amount of DRAM allocated at compile time. ``Remain`` indicates the amount of DRAM left to be used as heap memory at runtime. Note that due to meta data overhead, implementation constraints, and startup heap allocations, the actual size of the DRAM heap is smaller. + + - ``.data``: Amount of DRAM allocated at compile time for the ``.data`` (i.e., all statically allocated variables that are initialized to non-zero values). ``.data`` also consumes space in the binary image to store the non-zero initialization values. + + - ``.bss``: Amount of DRAM allocated at compile time for ``.bss`` (i.e., all statically allocated variables that are initialized to zero). ``.bss`` does not consume extra space in flash. + +- ``IRAM``: Total amount of IRAM allocated at compile time. ``Remain`` indicates the amount of IRAM left to be used as heap memory at runtime. Note that due to meta data overhead, implementation constraints, and startup heap allocations, the actual size of the IRAM heap is smaller. + + - ``.text``: Amount of IRAM used for ``.text`` (i.e., all code that is executed from :ref:`IRAM `). ``.text`` also consumes space in the binary image as the code is initially stored there and is then copied over to IRAM on startup. + +- ``Flash Code``: Code executed from flash. + + - ``.text``: Amount of flash used for ``.text`` (i.e., all code that is executed via the flash cache, see :ref:`IROM `). +- ``Flash Data``: Data stored in flash. + + - ``.rodata``: Amount of flash used for ``.rodata`` (i.e., read-only data that is loaded via the flash cache, see :ref:`DROM `). + +- ``Total image size`` is the estimated total size of the binary file. + +Component Usage Summary ``idf.py size-components`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The summary output from ``idf.py size`` lacks sufficient detail to identify the primary cause of excessive binary size. For a more detailed analysis, use ``idf.py size-components``, which indicates the contribution of each static library archive to the final binary size. + +.. code-block:: bash + + $ idf.py size-components + Per-archive contributions to ELF file + ┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ + ┃ Archive File ┃ Total Size ┃ DRAM ┃ .bss ┃ .data ┃ IRAM ┃ .text ┃ .vectors ┃ Flash Code ┃ .text ┃ Flash Data ┃ .rodata ┃ .appdesc ┃ RTC SLOW ┃ .rtc_slow_reserved ┃ + ┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ + │ libnet80211.a │ 116712 │ 9454 │ 8393 │ 1061 │ 5310 │ 5310 │ 0 │ 89698 │ 89698 │ 12250 │ 12250 │ 0 │ 0 │ 0 │ + │ libmbedcrypto.a │ 105863 │ 141 │ 81 │ 60 │ 0 │ 0 │ 0 │ 71251 │ 71251 │ 34471 │ 34471 │ 0 │ 0 │ 0 │ + │ liblwip.a │ 85394 │ 2470 │ 2458 │ 12 │ 0 │ 0 │ 0 │ 79486 │ 79486 │ 3438 │ 3438 │ 0 │ 0 │ 0 │ + │ libpp.a │ 66484 │ 3915 │ 1444 │ 2471 │ 20004 │ 20004 │ 0 │ 37714 │ 37714 │ 4851 │ 4851 │ 0 │ 0 │ 0 │ + │ libc.a │ 59525 │ 576 │ 316 │ 260 │ 0 │ 0 │ 0 │ 55513 │ 55513 │ 3436 │ 3436 │ 0 │ 0 │ 0 │ + │ libesp_app_format.a │ 53209 │ 10 │ 10 │ 0 │ 0 │ 0 │ 0 │ 417 │ 417 │ 52782 │ 52526 │ 256 │ 0 │ 0 │ + │ libwpa_supplicant.a │ 45251 │ 1241 │ 1233 │ 8 │ 0 │ 0 │ 0 │ 42315 │ 42315 │ 1695 │ 1695 │ 0 │ 0 │ 0 │ + │ libphy.a │ 44360 │ 1229 │ 637 │ 592 │ 8922 │ 8922 │ 0 │ 34209 │ 34209 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libfreertos.a │ 21108 │ 3841 │ 741 │ 3100 │ 15594 │ 15594 │ 0 │ 467 │ 467 │ 1206 │ 1206 │ 0 │ 0 │ 0 │ + │ libesp_hw_support.a │ 15147 │ 256 │ 96 │ 160 │ 5654 │ 5654 │ 0 │ 8264 │ 8264 │ 949 │ 949 │ 0 │ 24 │ 24 │ + │ libnvs_flash.a │ 14522 │ 24 │ 24 │ 0 │ 0 │ 0 │ 0 │ 14250 │ 14250 │ 248 │ 248 │ 0 │ 0 │ 0 │ + │ libesp_system.a │ 13304 │ 793 │ 313 │ 480 │ 4267 │ 4267 │ 0 │ 7575 │ 7575 │ 669 │ 669 │ 0 │ 0 │ 0 │ + │ libhal.a │ 13078 │ 4000 │ 8 │ 3992 │ 5810 │ 5810 │ 0 │ 3143 │ 3143 │ 125 │ 125 │ 0 │ 0 │ 0 │ + │ libheap.a │ 12009 │ 12 │ 8 │ 4 │ 7298 │ 7298 │ 0 │ 3109 │ 3109 │ 1590 │ 1590 │ 0 │ 0 │ 0 │ + │ libspi_flash.a │ 11613 │ 1348 │ 24 │ 1324 │ 8932 │ 8932 │ 0 │ 865 │ 865 │ 468 │ 468 │ 0 │ 0 │ 0 │ + │ libesp_driver_uart.a │ 7255 │ 228 │ 32 │ 196 │ 0 │ 0 │ 0 │ 6434 │ 6434 │ 593 │ 593 │ 0 │ 0 │ 0 │ + │ libesp_netif.a │ 5954 │ 33 │ 29 │ 4 │ 0 │ 0 │ 0 │ 5758 │ 5758 │ 163 │ 163 │ 0 │ 0 │ 0 │ + │ libvfs.a │ 4180 │ 236 │ 44 │ 192 │ 0 │ 0 │ 0 │ 3757 │ 3757 │ 187 │ 187 │ 0 │ 0 │ 0 │ + │ libesp_mm.a │ 4003 │ 160 │ 124 │ 36 │ 1002 │ 1002 │ 0 │ 2627 │ 2627 │ 214 │ 214 │ 0 │ 0 │ 0 │ + │ libesp_wifi.a │ 3919 │ 527 │ 47 │ 480 │ 357 │ 357 │ 0 │ 2993 │ 2993 │ 42 │ 42 │ 0 │ 0 │ 0 │ + │ libesp_timer.a │ 3471 │ 56 │ 24 │ 32 │ 1621 │ 1621 │ 0 │ 1659 │ 1659 │ 135 │ 135 │ 0 │ 0 │ 0 │ + │ libxtensa.a │ 3412 │ 1044 │ 0 │ 1044 │ 2213 │ 1789 │ 424 │ 119 │ 119 │ 36 │ 36 │ 0 │ 0 │ 0 │ + │ libnewlib.a │ 3352 │ 360 │ 200 │ 160 │ 1535 │ 1535 │ 0 │ 1346 │ 1346 │ 111 │ 111 │ 0 │ 0 │ 0 │ + │ libesp_event.a │ 3137 │ 4 │ 4 │ 0 │ 0 │ 0 │ 0 │ 2992 │ 2992 │ 141 │ 141 │ 0 │ 0 │ 0 │ + │ libesp_phy.a │ 2400 │ 53 │ 36 │ 17 │ 235 │ 235 │ 0 │ 1868 │ 1868 │ 244 │ 244 │ 0 │ 0 │ 0 │ + │ libbootloader_support.a │ 1939 │ 0 │ 0 │ 0 │ 1805 │ 1805 │ 0 │ 94 │ 94 │ 40 │ 40 │ 0 │ 0 │ 0 │ + │ libesp_partition.a │ 1865 │ 8 │ 8 │ 0 │ 0 │ 0 │ 0 │ 1689 │ 1689 │ 168 │ 168 │ 0 │ 0 │ 0 │ + │ libesp_common.a │ 1793 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 51 │ 51 │ 1742 │ 1742 │ 0 │ 0 │ 0 │ + │ liblog.a │ 1706 │ 280 │ 272 │ 8 │ 276 │ 276 │ 0 │ 1102 │ 1102 │ 48 │ 48 │ 0 │ 0 │ 0 │ + │ libefuse.a │ 1672 │ 64 │ 4 │ 60 │ 0 │ 0 │ 0 │ 1427 │ 1427 │ 181 │ 181 │ 0 │ 0 │ 0 │ + │ libsoc.a │ 1540 │ 0 │ 0 │ 0 │ 37 │ 37 │ 0 │ 39 │ 39 │ 1464 │ 1464 │ 0 │ 0 │ 0 │ + │ libstdc++.a │ 1502 │ 21 │ 17 │ 4 │ 0 │ 0 │ 0 │ 1282 │ 1282 │ 199 │ 199 │ 0 │ 0 │ 0 │ + │ libesp_ringbuf.a │ 1121 │ 0 │ 0 │ 0 │ 1024 │ 1024 │ 0 │ 0 │ 0 │ 97 │ 97 │ 0 │ 0 │ 0 │ + │ libmain.a │ 1027 │ 8 │ 8 │ 0 │ 0 │ 0 │ 0 │ 964 │ 964 │ 55 │ 55 │ 0 │ 0 │ 0 │ + │ libpthread.a │ 678 │ 20 │ 12 │ 8 │ 0 │ 0 │ 0 │ 604 │ 604 │ 54 │ 54 │ 0 │ 0 │ 0 │ + │ libesp_vfs_console.a │ 599 │ 12 │ 12 │ 0 │ 0 │ 0 │ 0 │ 415 │ 415 │ 172 │ 172 │ 0 │ 0 │ 0 │ + │ libxt_hal.a │ 475 │ 0 │ 0 │ 0 │ 443 │ 443 │ 0 │ 0 │ 0 │ 32 │ 32 │ 0 │ 0 │ 0 │ + │ librtc.a │ 456 │ 0 │ 0 │ 0 │ 456 │ 456 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libcore.a │ 331 │ 33 │ 33 │ 0 │ 0 │ 0 │ 0 │ 255 │ 255 │ 43 │ 43 │ 0 │ 0 │ 0 │ + │ libesp_coex.a │ 277 │ 0 │ 0 │ 0 │ 118 │ 118 │ 0 │ 159 │ 159 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libapp_update.a │ 186 │ 4 │ 4 │ 0 │ 0 │ 0 │ 0 │ 152 │ 152 │ 30 │ 30 │ 0 │ 0 │ 0 │ + │ libesp_rom.a │ 102 │ 0 │ 0 │ 0 │ 102 │ 102 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libgcc.a │ 89 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 89 │ 89 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libcxx.a │ 52 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 52 │ 52 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ libnvs_sec_provider.a │ 5 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 5 │ 5 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ (exe) │ 3 │ 0 │ 0 │ 0 │ 3 │ 0 │ 3 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ + └─────────────────────────┴────────────┴──────┴──────┴───────┴───────┴───────┴──────────┴────────────┴───────┴────────────┴─────────┴──────────┴──────────┴────────────────────┘ + + +Generally, one static library archive is built per component, although some are binary libraries included by a particular component, for example, ``libnet80211.a`` is included by ``esp_wifi`` component. There are also toolchain libraries such as ``libc.a`` and ``libgcc.a`` listed here, these provide Standard C/C++ Library and toolchain built-in functionality. + +If the project is simple and only has a ``main`` component, then all of the project's code will be shown under ``libmain.a``. If the project includes its own components (see :doc:`/api-guides/build-system`), then they will each be shown on a separate line. + +The table is sorted in descending order of the total contribution of the static archive to the binary size. The columns indicate memory types and output sections as detailed in the Size Summary. + +.. note:: + + The ``(exe)`` archive is a special archive that contains object files directly linked into the final binary, meaning they are not part of any archive file. + +.. note:: + + The size of the ``.rodata`` section in the ``Flash Data`` memory type may appear very large for a single archive. This occurs due to linker relaxations. The linker may attempt to combine object file sections with ``MERGE`` and ``STRINGS`` flags from all archives into one to perform tail string optimization. Consequently, one archive may end up with a very large ``.rodata`` section, containing string literals from other archives. This is evident in the ``.rodata`` section of the ``libesp_app_format.a`` archive. + + +Source File Usage Summary ``idf.py size-files`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For even more details, run ``idf.py size-files`` to get a summary of the contribution each object file has made to the final binary size. Each object file corresponds to a single source file. + +.. code-block:: bash + + $ idf.py size-files + Per-file contributions to ELF file + ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓ + ┃ Object File ┃ Total Size ┃ DRAM ┃ .bss ┃ .data ┃ IRAM ┃ .text ┃ .vectors ┃ Flash Code ┃ .text ┃ Flash Data ┃ .rodata ┃ .appdesc ┃ RTC SLOW ┃ .rtc_slow_reserved ┃ + ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩ + │ esp_app_desc.c.obj │ 72313 │ 10 │ 10 │ 0 │ 0 │ 0 │ 0 │ 417 │ 417 │ 71886 │ 71630 │ 256 │ 0 │ 0 │ + │ x509_crt_bundle.S.obj │ 67810 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 67810 │ 67810 │ 0 │ 0 │ 0 │ + │ ecp_curves.c.obj │ 36415 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 6875 │ 6875 │ 29540 │ 29540 │ 0 │ 0 │ 0 │ + │ phy_chip_v7.o │ 19384 │ 783 │ 533 │ 250 │ 2186 │ 2186 │ 0 │ 16415 │ 16415 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ wl_cnx.o │ 18567 │ 3891 │ 3889 │ 2 │ 277 │ 277 │ 0 │ 13343 │ 13343 │ 1056 │ 1056 │ 0 │ 0 │ 0 │ + │ ieee80211_output.o │ 15498 │ 27 │ 25 │ 2 │ 2083 │ 2083 │ 0 │ 12840 │ 12840 │ 548 │ 548 │ 0 │ 0 │ 0 │ + │ pp.o │ 14722 │ 1207 │ 53 │ 1154 │ 7286 │ 7286 │ 0 │ 5590 │ 5590 │ 639 │ 639 │ 0 │ 0 │ 0 │ + │ libc_a-vfprintf.o │ 14084 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 13508 │ 13508 │ 576 │ 576 │ 0 │ 0 │ 0 │ + │ phy_chip_v7_cal.o │ 13997 │ 229 │ 54 │ 175 │ 4039 │ 4039 │ 0 │ 9729 │ 9729 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ pm.o │ 13958 │ 532 │ 488 │ 44 │ 3630 │ 3630 │ 0 │ 8823 │ 8823 │ 973 │ 973 │ 0 │ 0 │ 0 │ + │ libc_a-svfprintf.o │ 13753 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 13177 │ 13177 │ 576 │ 576 │ 0 │ 0 │ 0 │ + │ ieee80211_sta.o │ 13711 │ 50 │ 38 │ 12 │ 1443 │ 1443 │ 0 │ 11181 │ 11181 │ 1037 │ 1037 │ 0 │ 0 │ 0 │ + │ ieee80211_ioctl.o │ 13479 │ 120 │ 116 │ 4 │ 271 │ 271 │ 0 │ 11127 │ 11127 │ 1961 │ 1961 │ 0 │ 0 │ 0 │ + │ ieee80211_scan.o │ 12037 │ 327 │ 309 │ 18 │ 0 │ 0 │ 0 │ 11119 │ 11119 │ 591 │ 591 │ 0 │ 0 │ 0 │ + │ ieee80211_hostap.o │ 11970 │ 42 │ 41 │ 1 │ 0 │ 0 │ 0 │ 10898 │ 10898 │ 1030 │ 1030 │ 0 │ 0 │ 0 │ + │ nd6.c.obj │ 11815 │ 940 │ 932 │ 8 │ 0 │ 0 │ 0 │ 10764 │ 10764 │ 111 │ 111 │ 0 │ 0 │ 0 │ + │ phy_chip_v7_ana.o │ 11039 │ 217 │ 50 │ 167 │ 2697 │ 2697 │ 0 │ 8125 │ 8125 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ ieee80211_ht.o │ 11033 │ 5 │ 4 │ 1 │ 1179 │ 1179 │ 0 │ 8466 │ 8466 │ 1383 │ 1383 │ 0 │ 0 │ 0 │ + │ sae.c.obj │ 11003 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 10971 │ 10971 │ 32 │ 32 │ 0 │ 0 │ 0 │ + │ tasks.c.obj │ 10753 │ 712 │ 696 │ 16 │ 9416 │ 9416 │ 0 │ 0 │ 0 │ 625 │ 625 │ 0 │ 0 │ 0 │ + │ libc_a-svfiprintf.o │ 10446 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 9398 │ 9398 │ 1048 │ 1048 │ 0 │ 0 │ 0 │ + │ libc_a-vfiprintf.o │ 10092 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 9516 │ 9516 │ 576 │ 576 │ 0 │ 0 │ 0 │ + │ wpa.c.obj │ 9688 │ 872 │ 872 │ 0 │ 0 │ 0 │ 0 │ 8816 │ 8816 │ 0 │ 0 │ 0 │ 0 │ 0 │ + │ tcp_in.c.obj │ 8904 │ 52 │ 52 │ 0 │ 0 │ 0 │ 0 │ 8698 │ 8698 │ 154 │ 154 │ 0 │ 0 │ 0 │ + [... additional lines removed ...] + + +The table is sorted in descending order of the total contribution of the object files to the binary size. The columns indicate memory types and output sections as detailed in the Size Summary. + +For example, we can see that the file ``x509_crt_bundle.S.o`` contributed 67,810 bytes to the total firmware size, all as ``.rodata`` in flash. Therefore we can guess that this application is using the :doc:`/api-reference/protocols/esp_crt_bundle` feature and not using this feature would save at last this many bytes from the firmware size. + +Some of the object files are linked from binary libraries and therefore you will not find a corresponding source file. To locate which component a source file belongs to, it is generally possible to search in the ESP-IDF source tree or look in the :ref:`linker-map-file` for the full path. + +Comparing Two Binaries +^^^^^^^^^^^^^^^^^^^^^^ + +When making changes that impact binary size, you can use the IDF Size tool to analyze the precise differences in size. The ``--diff`` option can be used with all previously mentioned sub-commands, allowing you to specify a path to a project build for comparison with the current project. + +For example to compare two ``hello_world`` project builds, follow these steps. First, create two copies of the ``hello_world`` project directory. Name the first project directory ``hello_world_Og``. This project will use the default :ref:`CONFIG_COMPILER_OPTIMIZATION` compiler optimization setting ``Debug (-Og)`` and will serve as the ``REFERENCE`` project. Name the second project directory ``hello_world_Os``. This project will use the ``Optimize for size (-Os)`` setting, which can be enabled using ``idf.py menuconfig``. This will be the ``CURRENT`` project. Build both projects. Then, from within the ``hello_world_Os`` project directory, run the following command: + + +.. code-block:: bash + + $ idf.py size --diff ../hello_world_Og + + CURRENT project file: "hello_world_Os/build/hello_world.map" + REFERENCE project file: "hello_world_Og/build/hello_world.map" + Difference is counted as CURRENT - REFERENCE, i.e. a positive number means that CURRENT is larger. + Memory Type Usage Summary + ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ + ┃ Memory Type/Section ┃ Used [bytes] ┃ Used [%] ┃ Remain [bytes] ┃ Total [bytes] ┃ + ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ + │ Flash Code │ 74498 -6168 │ 2.23 -0.18 │ 3267806 +6168 │ 3342304 0 │ + │ .text │ 74498 -6168 │ 2.23 -0.18 │ │ │ + │ IRAM │ 45539 -6296 │ 34.74 -4.8 │ 85533 +6296 │ 131072 0 │ + │ .text │ 44511 -6296 │ 33.96 -4.8 │ │ │ + │ Flash Data │ 35784 -2440 │ 0.85 -0.06 │ 4158488 +2440 │ 4194272 0 │ + │ .rodata │ 35528 -2440 │ 0.85 -0.06 │ │ │ + │ DRAM │ 10844 -392 │ 6.0 -0.22 │ 169892 +392 │ 180736 0 │ + │ .data │ 8612 -376 │ 4.76 -0.21 │ │ │ + │ .bss │ 2232 -16 │ 1.23 -0.01 │ │ │ + └─────────────────────┴──────────────┴──────────────┴────────────────┴────────────────┘ + Total image size: 164432 -15280 bytes (.bin may be padded larger) + +In addition to the previously mentioned Size Summary example, each column now also shows the size differences. Each difference is shown as ``CURRENT - REFERENCE``, meaning the current project sizes minus the sizes in the project specified with the `--diff` option. In this example, the final binary image of the ``hello_world_Os`` project is 15,280 bytes smaller than that of the ``hello_world_Og`` project. Additionally, the ``hello_world_Os`` project uses 6,168 bytes less in `Flash Code` memory, leaving 6,168 bytes more available in ``Flash Code``, with no difference in the total available memory. + +You can also use the diff mode to generate a table showing the differences at the component level (static library archive): + +.. code-block:: bash + + $ idf.py size-components --diff ../hello_world_Og + +Additionally, at the level of each individual source file: + +.. code-block:: bash + + $ idf.py size-files --diff ../hello_world_Og + +.. _idf-size-linker-failed: + +Showing Size When Linker Fails +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If too much static memory is allocated, the linker will fail with an error such as ``DRAM segment data does not fit``, ``region `iram0_0_seg' overflowed by 44 bytes``, or similar. + +In these cases, ``idf.py size`` will also fail. However, you can run ``idf_size.py``, which is a convenient wrapper that allows you to call ``esp-idf-size`` directly from within the ESP-IDF environment and see the partial static memory usage. The ``idf_size.py`` script requires a link map file as an argument, which is located in the project's build directory as ``.map``. + +.. code-block:: bash + + $ idf_size.py .map + warning: DRAM overflow detected!: output section or its part .dram0.bss(addr: 1073422848, size: 2240) does not fit into any memory region and will be assigned to the preceding dram0_0_seg memory region + warning: DRAM overflow detected!: output section or its part .dram0.data(addr: 1073414144, size: 8704) does not fit into any memory region and will be assigned to the preceding dram0_0_seg memory region + Memory Type Usage Summary + ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ + ┃ Memory Type/Section ┃ Used [bytes] ┃ Used [%] ┃ Remain [bytes] ┃ Total [bytes] ┃ + ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ + │ Flash Code │ 79759 │ 2.39 │ 3262545 │ 3342304 │ + │ .text │ 79759 │ 2.39 │ │ │ + │ IRAM │ 51106 │ 38.99 │ 79966 │ 131072 │ + │ .text │ 50079 │ 38.21 │ │ │ + │ .vectors │ 1027 │ 0.78 │ │ │ + │ Flash Data │ 38576 │ 0.92 │ 4155696 │ 4194272 │ + │ .rodata │ 38320 │ 0.91 │ │ │ + │ .appdesc │ 256 │ 0.01 │ │ │ + │ DRAM │ 10944 │ 0 │ -10944 │ 0 │ + │ .data_overflow │ 8704 │ 0 │ │ │ + │ .bss_overflow │ 2240 │ 0 │ │ │ + └─────────────────────┴──────────────┴──────────┴────────────────┴───────────────┘ + Total image size: 178145 bytes (.bin may be padded larger) + +Sections that do not fit into the memory region will have the suffix ``_overflow``. + +.. _esp-idf-size: https://github.com/espressif/esp-idf-size diff --git a/docs/en/api-guides/tools/index.rst b/docs/en/api-guides/tools/index.rst index 2f3251c3a2..1b25030209 100644 --- a/docs/en/api-guides/tools/index.rst +++ b/docs/en/api-guides/tools/index.rst @@ -11,4 +11,5 @@ Tools idf-component-manager idf-clang-tidy idf-tools + idf-size :esp32 or esp32c3: qemu diff --git a/docs/zh_CN/api-guides/performance/size.rst b/docs/zh_CN/api-guides/performance/size.rst index a8731a8455..1a9545e7dc 100644 --- a/docs/zh_CN/api-guides/performance/size.rst +++ b/docs/zh_CN/api-guides/performance/size.rst @@ -3,8 +3,6 @@ :link_to_translation:`en:[English]` -{IDF_TARGET_REDUCED_BY_IRAM: default="DRAM", esp32="IRAM 和/或 DRAM(取决于大小)"} - ESP-IDF 构建系统会编译项目和 ESP-IDF 中所有源文件,但只有程序实际引用的函数和变量才会链接到最终的二进制文件中。在某些情况下,需要减小固件二进制文件的总大小,例如,为使固件适配 flash 分区大小。 要减小固件二进制文件总大小,首先要找到导致其大小增加的原因。 @@ -14,312 +12,12 @@ ESP-IDF 构建系统会编译项目和 ESP-IDF 中所有源文件,但只有程 测量静态数据大小 --------------------------- -为了优化固件二进制文件大小和内存使用,需要测量项目中静态分配的 RAM (``data``, ``bss``),代码 (``text``) 和只读数据 (``rodata``)。 - -使用 :ref:`idf.py` 的子命令 ``size``, ``size-components`` 和 ``size-files`` 可以输出项目使用内存概况: - -.. note:: - - 添加 ``-DOUTPUT_FORMAT=csv`` 或 ``-DOUTPUT_FORMAT=json``,即可用 CSV 或 JSON 格式输出文件。 - -数据大小概况 ``idf.py size`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. only:: esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used static DRAM: 10608 bytes ( 170128 remain, 5.9% used) - .data size: 8464 bytes - .bss size: 2144 bytes - Used static IRAM: 48834 bytes ( 82238 remain, 37.3% used) - .text size: 47807 bytes - .vectors size: 1027 bytes - Used Flash size : 117391 bytes - .text: 80103 bytes - .rodata: 37032 bytes - Total image size: 174689 bytes (.bin may be padded larger) - - -.. only:: not esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used stat D/IRAM: 53743 bytes ( 122385 remain, 30.5% used) - .data size: 6504 bytes - .bss size: 1984 bytes - .text size: 44228 bytes - .vectors size: 1027 bytes - Used Flash size : 118879 bytes - .text: 83467 bytes - .rodata: 35156 bytes - Total image size: 170638 bytes (.bin may be padded larger) - -该输出结果细分了固件二进制文件中所有静态内存区域的大小: - -.. only:: esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used static DRAM: 10608 bytes ( 170128 remain, 5.9% used) - .data size: 8464 bytes - .bss size: 2144 bytes - Used static IRAM: 48834 bytes ( 82238 remain, 37.3% used) - .text size: 47807 bytes - .vectors size: 1027 bytes - Used Flash size : 117391 bytes - .text: 80103 bytes - .rodata: 37032 bytes - Total image size: 174689 bytes (.bin may be padded larger) - - - ``Used static DRAM``:编译时分配的 DRAM 大小。 ``remain`` 表示在运行时可用作堆内存的 DRAM 余量。请注意,由于元数据开销、实现限制和启动时的堆分配,实际的 DRAM 堆会更小。 - - - ``.data size``:编译时为 ``.data`` (即所有初始化值为非零值的静态变量)分配的 DRAM 大小。 ``.data`` 还在二进制映像中占用空间来存储非零初始化值。 - - ``.bss size``:编译时为 ``.bss`` (即所有初始化值为零的静态变量)分配的 DRAM 大小。``.bss`` 不会在 flash 中占用额外空间。 - - - ``Used static IRAM``:编译时分配的 IRAM 大小。 ``remain`` 表示在运行时可用作堆内存的 IRAM 余量。请注意,由于元数据开销、实现限制和启动时的堆分配,实际的 IRAM 堆会更小。 - - - ``.text size``:用于 ``.text`` 的 IRAM 大小(即所有从 :ref:`IRAM ` 执行的代码)。由于代码最初存储在 ``.text`` 中,在启动时才会复制到 IRAM,因此 ``.text`` 在二进制映像中也会占用空间。 - - - ``Used Flash size``:使用的 flash 大小(不包括 DRAM 和 IRAM 的使用量)。 - - - ``.text``:用于 ``.text`` (即通过 flash 缓存执行的所有代码,请参阅 :ref:`IROM `)的 flash 大小。 - - ``.rodata``:用于 ``.rodata`` (即通过 flash 缓存加载的只读数据,参阅 :ref:`DROM `)的 flash 大小。 - - - ``Total image size`` 是二进制文件的预估总大小。 - -.. only:: not esp32 - - .. code-block:: bash - - $ idf.py size - [...] - Total sizes: - Used stat D/IRAM: 53743 bytes ( 122385 remain, 30.5% used) - .data size: 6504 bytes - .bss size: 1984 bytes - .text size: 44228 bytes - .vectors size: 1027 bytes - Used Flash size : 118879 bytes - .text: 83467 bytes - .rodata: 35156 bytes - Total image size: 170638 bytes (.bin may be padded larger) - - - ``Used stat D/IRAM``:编译时使用的 D/IRAM 大小。``remain`` 表示在运行时可用作堆内存的 D/IRAM 余量。请注意,由于元数据开销、实现限制和启动时的堆分配,实际的 DRAM 堆会更小。 - - - ``.data size``:编译时为 ``.data`` (即所有初始化值为非零值的静态变量)分配的 D/IRAM 大小。 ``.data`` 还在二进制映像中占用空间来存储非零初始化值。 - - ``.bss size``:编译时为 ``.bss`` (即所有初始化值为零的静态变量)分配的 D/IRAM 大小。``.bss`` 不会在 flash 中占用额外空间。 - - ``.text size``:用于 ``.text`` 的 D/IRAM 大小(即所有从内部 RAM 执行的代码)。由于代码最初存储在 ``.text`` 中,在启动时才会复制到 D/IRAM,因此 ``.text`` 在二进制映像中也会占用空间。 - - - ``Used Flash size``:使用的 flash 总大小(不包括 D/IRAM 的使用量)。 - - - ``.text``:用于 ``.text`` (即通过 flash 缓存执行的所有代码,请参阅 :ref:`IROM `)的 flash 大小。 - - ``.rodata``:用于 ``.rodata`` (即通过 flash 缓存加载的只读数据,参阅 :ref:`DROM `)的 flash 大小。 - - - ``Total image size`` is the estimated total size of the binary file. - - -组件使用概况 ``idf.py size-components`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``idf.py size`` 的输出结果不够详细,无法找出导致二进制文件过大的主要原因。要进行更详细的分析,请使用 ``idf.py size-components`` 。 - -.. code-block:: bash - - $ idf.py size-components - [...] - Total sizes: - DRAM .data size: 14956 bytes - DRAM .bss size: 15808 bytes - Used static DRAM: 30764 bytes ( 149972 available, 17.0% used) - Used static IRAM: 83918 bytes ( 47154 available, 64.0% used) - Flash code: 559943 bytes - Flash rodata: 176736 bytes - Total image size:~ 835553 bytes (.bin may be padded larger) - Per-archive contributions to ELF file: - Archive File DRAM .data & .bss & other IRAM D/IRAM Flash code & rodata Total - libnet80211.a 1267 6044 0 5490 0 107445 18484 138730 - liblwip.a 21 3838 0 0 0 97465 16116 117440 - libmbedtls.a 60 524 0 0 0 27655 69907 98146 - libmbedcrypto.a 64 81 0 30 0 76645 11661 88481 - libpp.a 2427 1292 0 20851 0 37208 4708 66486 - libc.a 4 0 0 0 0 57056 6455 63515 - libphy.a 1439 715 0 7798 0 33074 0 43026 - libwpa_supplicant.a 12 848 0 0 0 35505 1446 37811 - libfreertos.a 3104 740 0 15711 0 367 4228 24150 - libnvs_flash.a 0 24 0 0 0 14347 2924 17295 - libspi_flash.a 1562 294 0 8851 0 1840 1913 14460 - libesp_system.a 245 206 0 3078 0 5990 3817 13336 - libesp-tls.a 0 4 0 0 0 5637 3524 9165 - [... removed some lines here ...] - libesp_rom.a 0 0 0 112 0 0 0 112 - libcxx.a 0 0 0 0 0 47 0 47 - (exe) 0 0 0 3 0 3 12 18 - libesp_pm.a 0 0 0 0 0 8 0 8 - libesp_eth.a 0 0 0 0 0 0 0 0 - libmesh.a 0 0 0 0 0 0 0 0 - -``idf.py size-components`` 输出的前几行与 ``idf.py size`` 相同,此外还会输出 ``Per-archive contributions to ELF file`` 表格,显示每个静态库对最终二进制文件大小的贡献程度。 - -通常,每个组件都会构建一个静态库归档文件,尽管部分是由特定组件包含的二进制库,例如, ``esp_wifi`` 组件包含了 ``libnet80211.a``。此外,这里还列出了一些工具链库,例如 ``libc.a`` 和 ``libgcc.a``,用于提供 C/C++ 标准库和工具链内置功能。 - -对于只有一个 ``main`` 组件的简单项目,可在 ``libmain.a`` 目录下找到所有项目代码。若项目包含其特有组件(参阅 :doc:`/api-guides/build-system`),则每个组件将单独在一行中显示。 - -该表格按静态库归档文件对最终二进制文件大小的贡献程度降序排序。 - -各列含义如下: - -.. list:: - - - ``DRAM .data & .bss & other`` - ``.data`` 和 ``.bss`` 分别与上方显示的总数相同。两者都是静态变量,且都会减少运行时的可用 RAM,但 ``.bss`` 不会增加二进制文件大小。 ``other`` 列指任何会增加 RAM 大小的自定义数据段,该值通常为 0。 - :esp32: - ``IRAM`` - 该列与上方显示的总数相同,表示链接到从 IRAM 执行的代码,这些代码占用二进制文件空间,并且会减少执行 ``HEAP_CAP_32BIT`` 时可动态分配的 IRAM。 - :esp32: - ``D/IRAM`` - 显示了 IRAM 占用的空间。D/IRAM 占用的空间会减少运行时可用作堆内存的 DRAM 空间。 - :not esp32: - ``IRAM`` - 与上方显示的总数相同,表示链接到从 IRAM 执行的代码,这些代码占用二进制文件空间,并且会减少运行时可用作堆内存的 DRAM 空间。 - - ``Flash code & rodata`` - 这些值与上方显示总数相同,指通过 flash 缓存访问的 IROM 和 DROM 空间,对二进制文件大小的贡献。 - -源文件使用概况 ``idf.py size-files`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -要了解更多详情,请运行 ``idf.py size-files``,获取每个目标文件对最终二进制文件大小的贡献概况。每个目标文件对应一个单独的源文件。 - -.. code-block:: bash - - $ idf.py size-files - [...] - Total sizes: - DRAM .data size: 14956 bytes - DRAM .bss size: 15808 bytes - Used static DRAM: 30764 bytes ( 149972 available, 17.0% used) - Used static IRAM: 83918 bytes ( 47154 available, 64.0% used) - Flash code: 559943 bytes - Flash rodata: 176736 bytes - Total image size:~ 835553 bytes (.bin may be padded larger) - Per-file contributions to ELF file: - Object File DRAM .data & .bss & other IRAM D/IRAM Flash code & rodata Total - x509_crt_bundle.S.o 0 0 0 0 0 0 64212 64212 - wl_cnx.o 2 3183 0 221 0 13119 3286 19811 - phy_chip_v7.o 721 614 0 1642 0 16820 0 19797 - ieee80211_ioctl.o 740 96 0 437 0 15325 2627 19225 - pp.o 1142 45 0 8871 0 5030 537 15625 - ieee80211_output.o 2 20 0 2118 0 11617 914 14671 - ieee80211_sta.o 1 41 0 1498 0 10858 2218 14616 - lib_a-vfprintf.o 0 0 0 0 0 13829 752 14581 - lib_a-svfprintf.o 0 0 0 0 0 13251 752 14003 - ssl_tls.c.o 60 0 0 0 0 12769 463 13292 - sockets.c.o 0 648 0 0 0 11096 1030 12774 - nd6.c.o 8 932 0 0 0 11515 314 12769 - phy_chip_v7_cal.o 477 53 0 3499 0 8561 0 12590 - pm.o 32 364 0 2673 0 7788 782 11639 - ieee80211_scan.o 18 288 0 0 0 8889 1921 11116 - lib_a-svfiprintf.o 0 0 0 0 0 9654 1206 10860 - lib_a-vfiprintf.o 0 0 0 0 0 10069 734 10803 - ieee80211_ht.o 0 4 0 1186 0 8628 898 10716 - phy_chip_v7_ana.o 241 48 0 2657 0 7677 0 10623 - bignum.c.o 0 4 0 0 0 9652 752 10408 - tcp_in.c.o 0 52 0 0 0 8750 1282 10084 - trc.o 664 88 0 1726 0 6245 1108 9831 - tasks.c.o 8 704 0 7594 0 0 1475 9781 - ecp_curves.c.o 28 0 0 0 0 7384 2325 9737 - ecp.c.o 0 64 0 0 0 8864 286 9214 - ieee80211_hostap.o 1 41 0 0 0 8578 585 9205 - wdev.o 121 125 0 4499 0 3684 580 9009 - tcp_out.c.o 0 0 0 0 0 5686 2161 7847 - tcp.c.o 2 26 0 0 0 6161 1617 7806 - ieee80211_input.o 0 0 0 0 0 6797 973 7770 - wpa.c.o 0 656 0 0 0 6828 55 7539 - [... additional lines removed ...] - -文件总大小概况下方会显示 ``Per-file contributions to ELF file`` 表格。 - -该表格的列与上文运行 ``idy.py size-components`` 显示的列相同,但该表格的粒度更细,展示了每个目标文件对二进制文件大小的贡献。 - -例如,文件 ``x509_crt_bundle.S.o`` 对总固件大小贡献了 64,212 字节,全都存储在 flash 中的 ``.rodata`` 区域。由此可以推知,该应用程序正在使用 :doc:`/api-reference/protocols/esp_crt_bundle` 功能。如果不使用该功能,固件大小至少可以减少 64,212 字节。 - -某些目标文件从二进制库中链接至此,因此无法找到对应源文件。要确定一个源文件属于哪个组件,通常可以在 ESP-IDF 源代码树中搜索,或者在 :ref:`linker-map-file` 中查找完整路径。 - -比较两个二进制文件 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -如果某些改动影响了二进制文件大小,可以使用 ESP-IDF 工具来详细分析文件大小的确切差异。 - -该操作不是通过运行 ``idf.py`` 进行的,而是需要直接运行 Python 工具 `esp_idf_size `_ 。 - -执行该操作,首先需要在构建目录中找到链接器映射文件 ``PROJECTNAME.map``。 ``esp_idf_size`` 工具会基于链接器映射文件的输出结果分析文件大小差异。 - -要与另一个二进制文件进行比较,还需要保存该文件对应的 ``.map`` 文件,该文件位于构建目录中。 - -例如,要比较两个构建文件,其中一个使用默认的 :ref:`CONFIG_COMPILER_OPTIMIZATION` ``Debug (-Og)`` 配置,而另一个使用 ``Optimize for size (-Os)`` 配置: - -.. code-block:: bash - - $ python -m esp_idf_size --diff build_Og/https_request.map build_Os/https_request.map - MAP file: build_Os/https_request.map - MAP file: build_Og/https_request.map - Difference is counted as - , i.e. a positive number means that is larger. - Total sizes of : Difference - DRAM .data size: 14516 bytes 14956 -440 - DRAM .bss size: 15792 bytes 15808 -16 - Used static DRAM: 30308 bytes ( 150428 available, 16.8% used) 30764 -456 ( +456 available, +0 total) - Used static IRAM: 78498 bytes ( 52574 available, 59.9% used) 83918 -5420 ( +5420 available, +0 total) - Flash code: 509183 bytes 559943 -50760 - Flash rodata: 170592 bytes 176736 -6144 - Total image size:~ 772789 bytes (.bin may be padded larger) 835553 -62764 - -从 ``Difference`` 列可以看出,改变该设置导致整个二进制文件减小了 60 KB 以上,并且可用的 RAM 增加了 5 KB 以上。 - -还可以使用 ``diff`` 模式来输出表格,显示组件级(静态库)的差异: - -.. note:: - - 运行 ``esp_idf_size`` 时可以使用 ``--format`` 选项输出 JSON 或 CSV 格式的结果。 - -.. code-block:: bash - - python -m esp_idf_size --archives --diff build_Og/https_request.map build_Oshttps_request.map - -同样适用于比较单个源文件级的差异: - -.. code-block:: bash - - python -m esp_idf_size --files --diff build_Og/https_request.map build_Oshttps_request.map - -了解将输出写入文件等其他选项,可以输入 ``--help`` 查看完整列表。 - -.. _idf-size-linker-failed: - -链接器失败时显示文件大小 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -如果被分配的静态内存大小超越上限,链接器会失败并显示错误信息,例如 ``DRAM segment data does not fit`` 和 ``region `iram0_0_seg' overflowed by 44 bytes`` 等。 - -在这些情况下, ``idf.py size`` 也无法成功执行。然而,通过手动运行 ``esp_idf_size``,可以查看 **部分静态内存使用情况** 。内存使用情况将不包含无法链接的变量,因此仍然会显示有部分可用空间。 - -映射文件参数为构建目录下的 ``.map`` 文件。 - -.. code-block:: bash - - python -m esp_idf_size build/project_name.map - -还可以查看类似于 ``size-components`` 或 ``size-files`` 输出的内容: - -.. code-block:: bash - - python -m esp_idf_size --archives build/project_name.map - python -m esp_idf_size --files build/project_name.map +为了优化固件二进制文件大小和内存使用,需要测量项目中静态分配的 RAM (``data``, ``bss``),代码 (``text``) 和只读数据 (``rodata``)。:ref:`idf.py` 工具的子命令 ``size``、``size-components`` 和 ``size-files`` 可分别用于检查不同级别静态分配的 RAM 使用情况。详情请参阅 :doc:`/api-guides/tools/idf-size` 工具。 .. _linker-map-file: 链接器映射文件 -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------- .. note:: diff --git a/docs/zh_CN/api-guides/tools/idf-size.rst b/docs/zh_CN/api-guides/tools/idf-size.rst new file mode 100644 index 0000000000..7c33412d2c --- /dev/null +++ b/docs/zh_CN/api-guides/tools/idf-size.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-guides/tools/idf-size.rst diff --git a/docs/zh_CN/api-guides/tools/index.rst b/docs/zh_CN/api-guides/tools/index.rst index 6702bcd48f..44916de260 100644 --- a/docs/zh_CN/api-guides/tools/index.rst +++ b/docs/zh_CN/api-guides/tools/index.rst @@ -11,4 +11,5 @@ idf-component-manager idf-clang-tidy idf-tools + idf-size :esp32 or esp32c3: qemu