esp-rs / rust

Rust for the xtensa architecture. Built in targets for the ESP32 and ESP8266
https://www.rust-lang.org
Other
744 stars 39 forks source link

Measurement of a crate footprint #70

Closed georgik closed 3 years ago

georgik commented 3 years ago

Story: As a user, I'd like to know footprint of a create used in my project, so that I can decide whether to use the crate or not in my embedded project.

With Rust it's easy to add dependency like std or some crate. The embedded devices has limited resources and it's important to identify impact of adding a big crate. Adding big dependency might generate application which is not possible to deploy.

Explore and identify methods for measuring footprint of the code / Rust library. Dimensions to consider: memory consumption, storage space.

@JurajSadel PTAL

jessebraham commented 3 years ago

cargo-bloat will show the storage requirements per crate in the resulting executable.

MabezDev commented 3 years ago

Looking a bit closer, I'm not sure cargo bloat will suffice.

Perhaps we should explore using idf_size.py?

For anyone wanting to look into this, to get cargo to produce a map file, you'll need to add the following linker arguments:

rustflags = [
  "-C", "link-arg=-Wl,-Map=target/build.map",
]

After which, the produced map file will still have mangled names, so you'll need to run it through rustfilt.

JurajSadel commented 3 years ago

Just for clarification: For MSVC: rustflags = [ "-C", "link-arg=/MAP:build.map", ]

For GCC: rustflags = [ "-C", "link-arg=-Wl,-Map=build.map", ]

For LLD: rustflags = [ "-C", "link-arg=-Map=build.map", ]

N3xed commented 3 years ago

Just a note for cargo bloat: You can specify the symbols section that it's going to look at, so that would be .iram0.text and .flash.text (you can only specify one section right now).

JurajSadel commented 3 years ago

I've been playing with idf_size.py.

The memory statistics of ( https://github.com/espressif/rust-esp32-example ) with per-archive contributions to ELF file looks like this:

python $IDF_PATH\tools\idf_size.py --archives build\esp32-hello-rust.map (Windows)
$IDF_PATH/tools/idf_size.py --archives build/esp32-hello-rust.map    (Linux)
Total sizes:
Used static DRAM:   11332 bytes ( 169404 remain, 6.3% used)
      .data size:    9068 bytes
      .bss  size:    2264 bytes
Used static IRAM:   44415 bytes (  86657 remain, 33.9% used)
      .text size:   43388 bytes
   .vectors size:    1027 bytes
Used stat D/IRAM:   55747 bytes ( 256061 remain, 17.9% used)
      .data size:    9068 bytes
      .bss  size:    2264 bytes
      .text size:   43388 bytes
   .vectors size:    1027 bytes
Used Flash size :  113691 bytes
      .text     :   84103 bytes
      .rodata   :   29332 bytes
Total image size:  220657 bytes (.bin may be padded larger)
Per-archive contributions to ELF file:
            Archive File DRAM .bss & 0.data Flash .appdesc & .rodata & .text IRAM0 .text & 0.vectors .rtc.data flash_total ram_st_total
                   (exe)         0        0              0        12       3           0           3         0          18            3
         libapp_update.a        12        1            256       129     174         194           0         0         754          207
 libbootloader_support.a         0        0              0         0     115        1421           0         0        1536         1421
                  libc.a         0        4              0      4270   55038           0           0         0       59312            4
               libclib.a         0        0              0        28      24           0           0         0          52            0
                libcxx.a         0        0              0         0       5           0           0         0           5            0
             libdriver.a        53       72              0       601    3435           0           0         0        4108          125
              libefuse.a         4       28              0       780    1339           0           0         0        2147           32
         libesp_common.a         0        0              0      7287      53           0           0         0        7340            0
     libesp_hw_support.a        30      176              0       387    2950        3953           0        16        7482         4175
            libesp_ipc.a        88       28              0       273     539         714           0         0        1554          830
        libesp_ringbuf.a         0        0              0       512       0         854           0         0        1366          854
            libesp_rom.a         0        0              0         0       0         112           0         0         112          112
         libesp_system.a       210      205              0      3809    5936        2901           0         0       12851         3316
          libesp_timer.a        24       32              0       574     893         894           0         0        2393          950
           libfreertos.a       740     3104              0      3516     237       13064         425         0       20346        17333
                libhal.a         0      287              0       936    1514        4165           0         0        6902         4452
               libheap.a         8     1962              0      2320    1661        5039           0         0       10982         7009
                liblog.a       272        8              0       123     488         238           0         0         857          518
               libmain.a         0        0              0       288     256           0           0         0         544            0
             libnewlib.a       440      237              0       340    1009        1408           0         0        2994         2085
            libpthread.a        12        8              0         0     264           0           0         0         272           20
            librustlib.a         0        0              0         0      53           0           0         0          53            0
          libspi_flash.a       294     1492              0      2198    1449        7360           0         0       12499         9146
                libvfs.a        48      308              0       468    6121           0           0         0        6897          356
             libxt_hal.a         0        0              0        32       0         443           0         0         475          443
             libxtensa.a         0     1024              0        35     126          77           0         0        1262         1101

For even more detailed statistics, use --files argument. It's also able to compare two binaries with --diff argument. For more information, please refer to ( https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/performance/size.html ).

idf_size.py also works on the ( https://github.com/ivmarkov/rust-esp32-std-hello ) but fails on the ( https://github.com/esp-rs/esp32-hal ) with error:

Traceback (most recent call last):
  File "/home/juraj/esp-idf/tools/idf_size.py", line 1185, in <module>
    main()
  File "/home/juraj/esp-idf/tools/idf_size.py", line 522, in main
    detected_target, segments, sections = load_map_data(args.map_file)
  File "/home/juraj/esp-idf/tools/idf_size.py", line 274, in load_map_data
    detected_chip = detect_target_chip(map_file)
  File "/home/juraj/esp-idf/tools/idf_size.py", line 333, in detect_target_chip
    raise RuntimeError('Target not detected')
RuntimeError: Target not detected
igrr commented 3 years ago

@JurajSadel good results so far! The list doesn't seem to include any Rust crates, only C static libraries which come from IDF. Can you look if Rust crates are reflected in the map file somehow, and if yes, what prevents idf_size.py from identifying them?

Regarding RuntimeError: Target not detected, can we work around this by using the target specified by idf_size.py's --target argument, if it is provided, and only call detect_target_chip if it isn't?

JurajSadel commented 3 years ago

@igrr thank you! I used the --files argument on https://github.com/ivmarkov/rust-esp32-std-hello and the small sample of the memory statistics looks like this:

Per-file contributions to ELF file:
             Object File DRAM .bss & 0.data Flash .rodata & .text IRAM0 .text & 0.vectors .rtc.data flash_total ram_st_total
libcompiler_builtins-687         0        0             0     148           0           0         0         148            0
libcompiler_builtins-687         0        0           160     150           0           0         0         310            0
libcompiler_builtins-687         0        0             0      95           0           0         0          95            0
libcompiler_builtins-687         0        0           158     469           0           0         0         627            0
libcompiler_builtins-687         0        0             0     185           0           0         0         185            0
libcore-7a2cc5bd9998b496         0        0           309    3227           0           0         0        3536            0
libcore-7a2cc5bd9998b496         0        0           462    2028           0           0         0        2490            0
libcore-7a2cc5bd9998b496         0        0             0     987           0           0         0         987            0
libcore-7a2cc5bd9998b496         0        0             0     721           0           0         0         721            0
libcore-7a2cc5bd9998b496         0        0            32     211           0           0         0         243            0
libcore-7a2cc5bd9998b496         0        0             0     631           0           0         0         631            0
libcore-7a2cc5bd9998b496         0        0          1907    1445           0           0         0        3352            0
libcore-7a2cc5bd9998b496         0        0           855     643           0           0         0        1498            0
libcore-7a2cc5bd9998b496         0        0           143     904           0           0         0        1047            0
libcore-7a2cc5bd9998b496         0        0           179    4416           0           0         0        4595            0
libcore-7a2cc5bd9998b496         0        0           281     129           0           0         0         410            0
libcore-7a2cc5bd9998b496         0        0           255    2004           0           0         0        2259            0
libcstr_core-011728cd952         0        0           176     292           0           0         0         468            0
libembedded_graphics-652         0        0            16      61           0           0         0          77            0
libembedded_graphics_cor         0        0             0       5           0           0         0           5            0
libembedded_svc-3abf7236         0        0           518    1488           0           0         0        2006            0
libembedded_svc-3abf7236         0        0           276     370           0           0         0         646            0
libembedded_svc-3abf7236         0        0            68     433           0           0         0         501            0
libembedded_svc-3abf7236         0        0           173     551           0           0         0         724            0
libembedded_svc-3abf7236         0        0           382     796           0           0         0        1178            0
libembedded_svc-3abf7236         0        0           878    2469           0           0         0        3347            0
libembedded_svc-3abf7236         0        0           570    1362           0           0         0        1932            0
libembedded_svc-3abf7236         0        0           211     912           0           0         0        1123            0
libembedded_svc-3abf7236         0        0           280    1118           0           0         0        1398            0
libembedded_svc-3abf7236         0        0             0     525           0           0         0         525            0
libembedded_svc-3abf7236         0        0           109     349           0           0         0         458            0
libembedded_svc-3abf7236         0        0           250     400           0           0         0         650            0
libenumset-f4236ef035df1         0        0           144     228           0           0         0         372            0
libesp_idf_svc-4f2f734d1         0        8          4422    9276           0           0         0       13706            8
libesp_idf_svc-4f2f734d1         0        0           605     732           0           0         0        1337            0
libesp_idf_svc-4f2f734d1         0        0            64     566           0           0         0         630            0
libesp_idf_svc-4f2f734d1         0        0           276     706           0           0         0         982            0
libesp_idf_svc-4f2f734d1         0        0           334     611           0           0         0         945            0
libesp_idf_svc-4f2f734d1         0        0            51     157           0           0         0         208            0
libesp_idf_svc-4f2f734d1         0        8           466     689           0           0         0        1163            8
libesp_idf_svc-4f2f734d1         0        0          1565    5388           0           0         0        6953            0
libesp_idf_svc-4f2f734d1         0        0          1440    2422           0           0         0        3862            0
libesp_idf_svc-4f2f734d1         0        0           173    1216           0           0         0        1389            0
libesp_idf_svc-4f2f734d1         0        8           813    1864           0           0         0        2685            8
libesp_idf_svc-4f2f734d1         0        8           748    1145           0           0         0        1901            8
libesp_idf_svc-4f2f734d1         0        0           345     429           0           0         0         774            0
libesp_idf_svc-4f2f734d1         0        0           442     277           0           0         0         719            0
libesp_idf_svc-4f2f734d1         0        0             0     236           0           0         0         236            0
libesp_idf_sys-f33521328         0        0             0      29           0           0         0          29            0
libesp_idf_sys-f33521328         0        0             0      17           0           0         0          17            0
libesp_idf_sys-f33521328         0        0             0     181           0           0         0         181            0
libesp_idf_sys-f33521328         0        0           397     258           0           0         0         655            0
libhashbrown-22bf0ba8d89         0        0           143      60           0           0         0         203            0
libhashbrown-22bf0ba8d89         0        0             0      12           0           0         0          12            0
libhttp_auth_basic-14612         0        0             0      19           0           0         0          19            0
liblog-ce623a4a2b171506.         8        8            78     285           0           0         0         371           16
libmemchr-a04c63f4a3f2a2         0        0           377     430           0           0         0         807            0
librustc_demangle-f2e98b         0        0             0      28           0           0         0          28            0
librustc_demangle-f2e98b         0        0             0       5           0           0         0           5            0
librustc_demangle-f2e98b         0        0           831    2134           0           0         0        2965            0
librustc_demangle-f2e98b         0        0           153     118           0           0         0         271            0
librustc_demangle-f2e98b         0        0          1176    4095           0           0         0        5271            0
librustc_demangle-f2e98b         0        0          1758    9541           0           0         0       11299            0
librustc_demangle-f2e98b         0        0             0      17           0           0         0          17            0
libserde_json-7dc1d58f59         0        0             0      26           0           0         0          26            0
libserde_json-7dc1d58f59         0        0             0      22           0           0         0          22            0
libserde_json-7dc1d58f59         0        0             0      17           0           0         0          17            0
libserde_json-7dc1d58f59         0        0             0      11           0           0         0          11            0
libstd-06b540ec5a53d87e.         4        8          1604    4752           0           0         0        6364           12
libstd-06b540ec5a53d87e.         0        0           927    2360           0           0         0        3287            0
libstd-06b540ec5a53d87e.        41        8           495    2036           0           0         0        2539           49
libstd-06b540ec5a53d87e.         0        0           827    1299           0           0         0        2126            0
libstd-06b540ec5a53d87e.         4        0          1268    2032           0           0         0        3300            4
libstd-06b540ec5a53d87e.         0       12          1381    3706           0           0         0        5099           12
libstd-06b540ec5a53d87e.         0       56           918    3589           0           0         0        4563           56
libstd-06b540ec5a53d87e.         4        0           963    1442           0           0         0        2405            4
libstd-06b540ec5a53d87e.         0       12          1500    3182           0           0         0        4694           12
libstd-06b540ec5a53d87e.         0        4           664    1777           0           0         0        2445            4
libstd-06b540ec5a53d87e.         4        8          1781    3414           0           0         0        5203           12
libstd-06b540ec5a53d87e.         4        0           580    2899           0           0         0        3479            4
libstd-06b540ec5a53d87e.         0        0          1462    4768           0           0         0        6230            0
libstd-06b540ec5a53d87e.         0        0          1531    5029           0           0         0        6560            0
liburl-85cbd9ea3b680d28.         0        0           230     120           0           0         0         350            0
liburl-85cbd9ea3b680d28.         0        0             0      21           0           0         0          21            0
liburl-85cbd9ea3b680d28.         0        0           173     341           0           0         0         514            0

It looks like idf_size is analyzing the Rust crates as well. Complete text output is here: idf_size --files rust-std-hello.txt idf_size also allows to save the memory statistics as json file with --json and -o OUT_FILE arguments.

Regarding the RuntimeError: Target not detected I tried the --target argument for the esp32-hal project but it didn't resolve the problem with target chip detection. However, I found that https://github.com/ivmarkov/rust-esp32-std-hello has some additional generated lines, which https://github.com/esp-rs/esp32-hal doesn't have in Linker script and memory map section in the map file:

LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/no-rtti/crt0.o
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/crti.o
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/crtbegin.o
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/no-rtti/libm.a
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcc.a
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/no-rtti/libstdc++.a
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/libgcov.a
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/lib/no-rtti/libc.a
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/crtend.o
LOAD /home/juraj/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/no-rtti/crtn.o

If there is just one of these platformio/packages/toolchain-xtensa32/...., the detect_target_chip() and idf_size works fine, otherwise it ends with RuntimeError: Target not detected just like esp32-hal example.

georgik commented 3 years ago

Next steps:

JurajSadel commented 3 years ago