Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: One function adds 21,736 bytes to total flash count?

  1. #1
    Senior Member
    Join Date
    Nov 2012
    Posts
    412

    One function adds 21,736 bytes to total flash count?

    One function adds 21,736 bytes to total flash count?
    Also, it adds 1226 for ram usage?

    Before
    Binary sketch size: 51,172 bytes (of a 131,072 byte maximum)
    Estimated memory use: 4,680 bytes (of a 16,384 byte maximum)

    Using
    sprintf(str,"%d",abs(networktime));

    After
    Binary sketch size: 72,908 bytes (of a 131,072 byte maximum)
    Estimated memory use: 5,908 bytes (of a 16,384 byte maximum)

    Code snippet- counts the number of chars in a integer
    Code:
    long x = 0;
    char str[20];      
    sprintf(str,"%d",abs(networktime));
    x = (strlen(str));
    Serial.println(x);
    win xp/sp3
    beta12
    Last edited by t3andy; 02-07-2013 at 11:39 PM. Reason: addition

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,225
    Yes, newlib's printf and scanf implementations are huge.

  3. #3
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,099
    Well sprintf is a rather large function. Look at the documentation for it, it has to have code to handle all of the different formats, and different sized data types.

    You didn't mention if it was teensy 1/2/2++ or 3.0. I suspect in addition to the size of the the code for sprintf and all of the functions it calls, the teensy 3.0 may bring in the entire floating point emulator, since sprintf supports %g, %f, etc. to print floating point. The AVR port for Arduino (and presumably teensy 1/2/2++) compiles its sprintf without support for %f, %g, etc. so it doesn't drag in the emulator.

    There are better ways to do what you want (looping, dividing by 10 to get the number of digits would probably be the smallest, or calling itoa instead of sprintf would be simpler)

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,225
    I've considered porting the avr-libc version. But at this point, with the only downside being extra memory usage, it's a really low priority.

    However, if someone were to do this porting, I'd happily accept a patch.......

  5. #5
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    486
    Quote Originally Posted by PaulStoffregen View Post
    Yes, newlib's printf and scanf implementations are huge.
    Is there a better (smaller) version ? I use it frequently to ensure my outputs are formatted cleanly. The floating point is the only portion I could perhaps work around.

    e.g. sprintf(DataLine, "%4i %3s %3s %2i %2d:%02d:%02d Internal Temp # %9ld = %6.2f deg.C%s\n", Set6Y, DOW[dayofweek(Set6Y, Set6Month, Set6D)], Month[Set6Month-1], Set6D, (iLastTime/3600) % 24, (iLastTime/60) % 60, iLastTime % 60, rollingCounter++, temperatureC, CRLF);

  6. #6
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    You didn't mention if it was teensy 1/2/2++ or 3.0.
    Teensy 3 using beta 12

  7. #7
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,099

    Cool

    The arm toolchain uses newlib as a base. Back when I was doing embedded toolchains, I recall that there was a variant of the *printf family that was compiled without floating point support. So if you change all 'sprintf' calls to 'siprintf' calls, it will save some amount of memory. I always wanted to add an option to GCC for newlib toolchains that would convert calls to sprintf to siprintf if there were no long, long longs, or floating point passed, but it was never a high enough of a priority to do the work.

    Lets see, if I compiled a simple sketch that calls sprintf in the setup function:

    • 32,164 bytes of text space, and 5,376 bytes of read/write data if I use sprintf;
    • 16,488 bytes of text space, and 5,252 bytes of read/write data if I use siprintf.
    Last edited by MichaelMeissner; 02-08-2013 at 03:10 AM.

  8. #8
    Senior Member
    Join Date
    Nov 2012
    Posts
    412
    I checked the function sprintf(); on the AVR and it only adds ~ 2k to the flash count.

  9. #9
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,099
    It is likely the AVR sprintf doesn't have all of the various formats that siprintf does.

    Another thing is how compact the encoding is for the AVR compared to the ARM. I haven't looked at either instruction set ISA in any detail.

    I believe that Teensy 3.0 actually supports normal printf/iprintf, and if so, it may be that doing that support drags in all of Serial support.

    Finally, one of these discussions highlighted that in the AVR world, all modules are compiled with -ffunction-sections and linked with -Wl,--gc-sections. These two options compile each function into a separate section, and then the linker eliminates all of the unused sections. That means if you have a package (say Serial.print) that has a bunch of methods for different types, and you only use one of type, the code for the other templates, etc. is not in the final linked images on the AVR, while it currently is linked in for the ARM.

    You would need somebody dedicated to tracking down where all of the stuff that is part of the final link comes from. I already have a day job that keeps me quite busy dealing with the GNU tools (and in fact, things will be heating up in a month or so in terms of future work), so I'm not stepping up to the task for doing something after hours. It isn't rocket science, but you need somebody with the time and energy to track down these things.

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    25,225
    Quote Originally Posted by MichaelMeissner View Post
    It isn't rocket science, but you need somebody with the time and energy to track down these things.
    Yup, indeed.

    Eventually I'll probably work on this... but most likely I would do so by porting the avr-libc code or something similar. Despite ARM's marketing info, AVR code does tend to compile larger on ARM. But it's not usually more than about 50% larger.

    Of course, this is a very low priority for me. It'll probably be about a year until I look at it.

  11. #11
    ugh.. no wonder my code went from 35k to 58k using snprintf....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •