Pages: [1]   Go Down
Author Topic: Code size with different versions and -flto optimization  (Read 775 times)
0 Members and 2 Guests are viewing this topic.
Offline Offline
Edison Member
*
Karma: 35
Posts: 1079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There has been some discussion about running different versions and about the size.
http://forum.arduino.cc/index.php?topic=261581

So I did a little test. I run the different versions in linux, and if they don't run I try the Windows verion in wine.
I grabbed a sketch to test the size. Version 0022 doesn't have the F() macro. So it is not a fair comparison.

Arduino 0022 (running in wine) : 24864 bytes
Arduino 1.0.5 : 26.358 bytes
Arduino 1.5.7 BETA : 25.728 bytes
Arduino 1.5.7 BETA with -flto option : 23.308 bytes
Arduino 1.5.7 BETA with -flto -funsafe-math-optimizations options : 22.920 bytes

The -flto option can be enabled in platform.txt

# These can be overridden in platform.local.txt
compiler.c.extra_flags=-Wextra -flto
compiler.c.elf.extra_flags=-w -flto
compiler.S.extra_flags=
compiler.cpp.extra_flags=-Wextra -flto
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=

I did a few more tests with -flto. A large sketch with Ethernet on the Mega was 10% smaller, but a very small sketch for a standalone ATmega8 was 25% smaller.
The "-funsafe-math-optimizations" is not 'unsafe', but it doesn't follow the exact IEEE rules. For calculating the temperature and humidity, there should be no problem to use it.

I would like to use these optimizations per project. Is it possible to set the options in the *.ino file ?
« Last Edit: August 21, 2014, 03:15:27 am by Peter_n » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



Arduino: 1.5.4 (Linux), Board: "Arduino Uno"
Peter
I have compiled one of my oldest sketches with 1.5.4 and 022 this is what I get

Arduino 1.5.4
Sketch uses 34,618 bytes (107%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,758 bytes (85%) of dynamic memory, leaving 290 bytes for local variables. Maximum is 2,048 bytes.
processing.app.debug.RunnerException: Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.
   at processing.app.Sketch.size(Sketch.java:1656)
   at processing.app.Sketch.build(Sketch.java:1570)
   at processing.app.Sketch.build(Sketch.java:1548)
   at processing.app.Editor$DefaultRunHandler.run(Editor.java:1915)
   at java.lang.Thread.run(Thread.java:744)

  This report would have more information with
  "Show verbose output during compilation"
  enabled in File > Preferences.
Arduino 022
avr-objcopy -O ihex -R .eeprom /tmp/build8939094106542793110.tmp/EnelWebLoggerS_v5mod.cpp.elf /tmp/build8939094106542793110.tmp/EnelWebLoggerS_v5mod.cpp.hex
Binary sketch size: 27202 bytes (of a 32256 byte maximum)

So the 1.5.4 is 25% bigger.
The sketch use several libraries and I think that most of the increase is due to the new libraries (eg. SDlib , Ethernetlib ......)

I have checked what I can do for the 1.5.7 :I am afraid is not installable ( I miss the file libastylej ) therefore I considering to use an editor and to compile and upload with the makefile: any suggestion on how to do it in the best way?

Paolo

 
Because of the Uno flash mem. limitation I will keep using 022 for the modification of that scketch.
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That iss disappointing, that Java is not the same as on other computers. Can you use an other computer ?
If you want, I can try to compile your sketch to see what the size is with 1.5.7 and the -flto option.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If I do some clean up I may try to install 1.5.7 in the XP laptop: it is matter of a couple of days.
Meanwhile if I can get a good makefile I can probably compile and build without the IDE.

Let see....

Paolo

Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been trying to optimize code size for myself.
Many compiler/linker options reduce the size for one sketch and increase it for another sketch. I did not find a good option that always reduces code size in addition to the -flto option (and the options already set by the Arduino IDE ofcourse).

The F() macro will reduce RAM usage.
And using the 'const' parameter for fixed value variables could reduce a sketch with 100 bytes. I had to change a few functions to accept 'const' values as parameter.
Floating point calculations can be avoided in many cases. For temperature and humidity I use an integer int 1/100 units.
Sometimes the Serial library is only used during development. I disable it for the final sketch, using a define 'DEBUG'.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I try to post a reply with the code..... but no success:why it is to big?
Meanwhile I start compiling on 1.5.7 with the makefile: what flag I should use?
It give me error because the def of routines follow the point in the code where they are called: this was accepted up to 1.5.4!!
Any flag to make it compatible with previous compilers

Paolo

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have finally installed ide 1.5.7!
I have tried the suggested modification to preference.txt but I have nt seen any change in the compiler flags.
The size I obtain it is still 34K .
I tried to get some other -flto flag example , but i cound not get any other post!

ANY HELP ON THIS????

Paolo
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I used "platform.txt", not "preferences.txt".
Look for the text "# These can be overridden in platform.local.txt", add the flags to the options in the following lines.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Finally I got it right!

Yes I obtained a significant reduction in size: now the sketch is about 32 k big from the 34.7 without optimisation.

This is very good but it is not enough: I have to work with the code and cut some useless part....
Thank you anyhow for this good result!
Logged

SF Bay Area (USA)
Online Online
Tesla Member
***
Karma: 134
Posts: 6763
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

well, analyze...
Try " avr-nm -S --demangle --size-sort *.elf" in your build directory:

avr-nm -S--demangle --size-sort *.elf
    :
0080012e 00000044 B rx_buffer
00800172 00000044 B tx_buffer
0000093e 00000048 T print_binary(unsigned char)
00001838 00000052 T HardwareSerial::read()
000019f4 00000054 T Print::write(unsigned char const*, unsigned int)
000015b6 00000076 T __vector_18
00001652 00000076 T __vector_19
0000153e 00000076 T init
000018aa 00000080 T HardwareSerial::write(unsigned char)
00001c38 00000080 T Print::print(long, int)
000013fc 00000090 T __vector_16
00000cb6 0000009a T print_fuse_extended()
0000192a 000000ac t global constructors keyed to rx_buffer
0000148c 000000b2 T delay
000009a6 000000b8 T print_boot_analysis()
00001ad0 000000c8 T Print::printNumber(unsigned long, unsigned char)
00000bae 00000108 T print_lock_bits()
000016c8 0000010e T HardwareSerial::begin(unsigned long)
00001014 0000013a T print_serno()
00000a5e 00000150 T print_signature()
00000d50 0000015a T print_fuse_high()
00000eaa 0000016a T print_fuse_low()
0000114e 0000028e T loop
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you
This is what I get(cutting the less significants lines):
Code:
avr-nm: supported targets: elf32-avr elf32-little elf32-big srec symbolsrec verilog tekhex binary ihex
tf101@tf101:/tmp/build3073111402836794477.tmp$ avr-nm -S --demangle --size-sort *.elf
00000ad8 0000001c T SPIClass::setClockDivider(unsigned char)
00800130 0000001c D vtable for Client [clone .local.78]
000072ce 0000001e T strncpy
00007a18 0000001e T __umulhisi3
00000286 0000001e T TwoWire::peek()
000072ae 00000020 T strncat
0080063f 00000020 B twi_masterBuffer.5573
0080066f 00000020 b twi_rxBuffer.5565.1731
0080061d 00000020 B twi_txBuffer.5575
000021b0 00000020 T PrintString(char*)
00002472 00000020 T W5100Class::execCmdSn(unsigned char, SockCMD) [clone .constprop.144]
000003e4 00000020 T EthernetUDP::remoteIP() [clone .local.45]
00000f24 00000020 T File::position()
008003cb 00000020 b _ZN7TwoWire8rxBufferE.2012
008003f3 00000020 B TwoWire::txBuffer
0080014c 00000020 D vtable for EthernetClient [clone .local.75]
000078e2 00000022 T __fp_round
000042fa 00000022 T SdFile::write(unsigned char)
00000310 00000024 T EthernetUDP::flush()
00003010 00000024 T File::close()
0000244e 00000024 T Print::println(long, int) [clone .constprop.159]
000007c8 00000024 T Print::println(char const*)
0080016c 00000024 d vtable for EthernetUDP [clone .local.73.1491]
000002a4 00000026 T TwoWire::read()
00006db2 00000028 T __divmodhi4
00006dda 00000028 T __udivmodhi4
000001b8 00000028 T HardwareSerial::read()
000007a0 00000028 T Print::println()
00002712 0000002a T EthernetUDP::stop()
00000334 0000002c T EthernetUDP::write(unsigned char)
0000039c 0000002c T EthernetClient::write(unsigned char)
000002e4 0000002c T EthernetServer::write(unsigned char)
00000404 0000002c T File::write(unsigned char)
000006b4 0000002c T Print::write(char const*) [clone .local.1]
00000a52 0000002c T SPIClass::begin()
00000a96 0000002e T analogRead
0000796c 0000002e T __divmodsi4
000076ee 00000030 T strncasecmp_P
00000baa 00000030 T W5100Class::readSnRX_RSR(unsigned char) [clone .local.15]
00000bda 00000030 t W5100Class::readSnTX_FSR(unsigned char) [clone .local.16.1816]
00002c3c 00000034 T EthernetClient::read()
00000e2e 00000034 T Sd2Card::readEnd()
000079e2 00000036 T __epilogue_restores__
000042c4 00000036 T File::write(unsigned char const*, unsigned int)
00000e62 00000036 T Sd2Card::waitNotBusy(unsigned int)
000079aa 00000038 T __prologue_saves__
00000c0a 00000038 T W5100Class::getTXFreeSize(unsigned char) [clone .constprop.95]
00002166 00000038 t W5100Class::getRXReceivedSize(unsigned char) [clone .constprop.141.1799]
00001930 00000038 t EthernetUDP::peek() [clone .1507]
00002b62 0000003a T EthernetUDP::read(unsigned char*, unsigned int)
000072f4 0000003c T atoi
000007ec 00000042 T HardwareSerial::_tx_udr_empty_irq()
00007904 00000044 T __fp_split3
00007a36 00000044 T __udivmodsi4
00000ca0 00000044 T W5100Class::write(unsigned int, unsigned char)
000008f8 00000044 T HardwareSerial::flush()
0000023e 00000046 t micros.1717
000077a0 00000048 T __fp_cmp
000021e4 00000048 T EthernetClient::connected()
00001032 00000048 T EthernetClient::EthernetClient(EthernetClient const&) [clone .local.59]
00001032 00000048 t EthernetClient::EthernetClient(EthernetClient const&) [clone .local.60.1973]
00800748 00000049 B SD
00000b60 0000004a T W5100Class::readSn(unsigned char, unsigned int) [clone .local.42]
00000668 0000004c T delay
0000431c 0000004c T __vector_19
00002c78 0000004c T EthernetClient::peek()
00000f44 0000004c T File::available()
00007330 0000004e T atol
00007388 0000004e T strtok_r
00000166 00000050 T Print::write(unsigned char const*, unsigned int)
00002b10 00000052 T EthernetUDP::read()
00002492 00000052 T EthernetUDP::endPacket()
0000107a 00000052 T TwoWire::write(unsigned char)
00003ba8 00000056 T callback_pathExists(SdFile&, char*, unsigned char, void*)
000036b4 00000056 T File::peek()
00006fb2 00000058 T __fixunssfsi
000010cc 0000005c t EthernetUDP::begin(unsigned int) [clone .1513]
00000c42 0000005e T W5100Class::write(unsigned int, unsigned char const*, unsigned int)
00000b00 00000060 T W5100Class::read(unsigned int, unsigned char*, unsigned int)
00004368 00000064 T __vector_18
00000dc4 00000064 T EthernetUDP::write(unsigned char const*, unsigned int)
0000222c 00000064 T Print::print(long, int) [clone .constprop.160]
000009e0 00000072 T pinMode
00000e98 00000072 T File::File(SdFile, char const*)
00000e98 00000072 t File::File(SdFile, char const*) [clone .1887]
00002f72 00000072 T SdFile::sync()
000025d0 00000076 T socket(unsigned char, unsigned char, unsigned int, unsigned char) [clone .part.0.5218] [clone .constprop.111]
00001bf2 00000076 T SdVolume::cacheFlush()
0000206c 00000078 T EthernetUDP::beginPacket(IPAddress, unsigned int)
00007726 0000007a T __floatunsisf
00003db4 0000007a T TwoWire::write(unsigned char const*, unsigned int)
000020e4 00000082 T IPAddress::printTo(Print&) const
0000273c 00000086 T EthernetClient::stop()
00002a86 0000008a t recv(unsigned char, unsigned char*, int) [clone .1693]
00001d90 00000092 T SdVolume::cacheRawBlock(unsigned long, unsigned char)
000043cc 00000094 T __vector_16
0000093c 0000009a T digitalWrite
00800691 0000009d B Serial
00002b9c 000000a0 T EthernetUDP::parsePacket()
00000f90 000000a2 T SdFile::SdFile(SdFile const&) [clone .local.56]
00000f90 000000a2 t SdFile::SdFile(SdFile const&) [clone .local.57.1963]
00002cc4 000000ac t SdVolume::freeChain(unsigned long) [clone .1670]
000006e0 000000b2 T Print::printNumber(unsigned long, unsigned char)
00006e32 000000c0 T __addsf3x
00007800 000000c2 T __mulsf3x
000029be 000000c8 T W5100Class::recv_data_processing(unsigned char, unsigned char*, unsigned int, unsigned char) [clone .constprop.142]
00000cfc 000000c8 T W5100Class::send_data_processing_offset(unsigned char, unsigned int, unsigned char const*, unsigned int) [clone .constprop.96]
00001a4a 000000c8 T Sd2Card::cardCommand(unsigned char, unsigned long)
0000082e 000000ca T HardwareSerial::write(unsigned char)
00006ef2 000000cc T __divsf3x
00002646 000000cc T EthernetServer::begin()
000024fe 000000d2 T EthernetClient::write(unsigned char const*, unsigned int)
0000371c 000000d6 T SdVolume::chainSize(unsigned long, unsigned long*) const
00001b12 000000e0 T Sd2Card::writeBlock(unsigned long, unsigned char const*)
00001968 000000e2 T EthernetServer::write(unsigned char const*, unsigned int)
00003492 000000ea t SdFile::addDirCluster() [clone .1591]
00001622 000000f2 t EthernetUDP::beginPacket(char const*, unsigned int) [clone .1526]
00001714 000000f2 T EthernetClient::connect(char const*, unsigned int)
000027c2 000000f8 T EthernetServer::accept()
000028ba 00000104 T EthernetServer::available()
00001e22 00000108 T SdVolume::fatGet(unsigned long, unsigned long*) const
0000714a 0000011e T free
00001c68 00000128 T Sd2Card::readData(unsigned long, unsigned int, unsigned int, unsigned char*) [clone .part.4.2706]
00001806 0000012a T EthernetClient::connect(IPAddress, unsigned int)
0000701a 00000130 T malloc
0000357c 00000138 T SdFile::seekSet(unsigned long)
000037f2 0000013e t SdFile::openCachedEntry(unsigned char, unsigned char) [clone .1541]
00001f2a 00000142 T SdVolume::fatPut(unsigned long, unsigned long)
000048aa 00000168 T openNewFile(int, int)
00003e2e 00000170 t walkPath(char*, SdFile&, unsigned char (*)(SdFile&, char*, unsigned char, void*), void*) [clone .constprop.149.1640]
00003bfe 000001b6 T callback_makeDirPath(SdFile&, char*, unsigned char, void*)
00002290 000001be T Print::printFloat(double, unsigned char)
00002d70 000001ee t SdFile::read() [clone .local.53.1616]
000046b6 000001f4 T SDClass::open(char const*, unsigned char) [clone .constprop.150]
0080041c 00000200 B SdVolume::cacheBuffer_
0000328e 00000204 T SdFile::addCluster()
00000430 00000238 T RTC_DS1307::now()
00004460 00000256 T __vector_24
00003034 0000025a T SdVolume::init(Sd2Card*, unsigned char) [clone .constprop.137]
00003930 00000278 T SdFile::open(SdFile*, char const*, unsigned char)
00007410 000002ce T strtod
00006aba 000002ea t global constructors keyed to 65535_0_EnelWebLoggerS_v5mod.cpp.o.6562.1413
00003f9e 00000326 t SdFile::write(void const*, unsigned int) [clone .1620]
00001128 000004fa t DNSClient::getHostByName(char const*, IPAddress&) [clone .1896]
00004a12 000020a8 T main
tf101@tf101:/tmp/build3073111402836794477.tmp$
What kind of indication can I get from those??
Thank you again.
Logged

SF Bay Area (USA)
Online Online
Tesla Member
***
Karma: 134
Posts: 6763
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What kind of indication can I get from those??
You should compare against output from the same command for the older compiler.
If each function has gotten a little bigger, you can say that the compiler is worse.
If the new version is including functions that you believe are not called, you can blame LTO and/or garbage collection (which I gather works slightly differently in the new compiler.)
If SOME functions have gotten significantly bigger, it could be new library versions that support new features.
Etc...

I've spent a lot of time doing such exercises.  Frankly, if your original program is 5% below the maximum, and  your new code is 10% over, you're pretty much screwed.  You can face a never-ending battle to keep your code below the limit, but you end up having to remove a feature every time you want to add one, and you would probably be better off looking for a new and bigger processor instead.  In your case, with the code size increasing 25% with no source change, I think it is worth further investigation.
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1079
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You use I2C, DS1307, SPI, Ethernet, SD, Serial.
That is something for the Arduino Mega 2560.

You can remove a complete part of the software. For example remove all the Serial functions (place them in between #define DEBUG or so) or all the floating point. Perhaps you can avoid floating point and use integers for the values and use for example the temperature in 1/100 degrees.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 30
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will do the comparison of the two compiler outputs 0022 ans 1.5.7: it may take a little time but it is interesting and , i hope ,worthwhile!

Thanks for all your suggestions!!
Logged

SF Bay Area (USA)
Online Online
Tesla Member
***
Karma: 134
Posts: 6763
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
That is something for the Arduino Mega 2560.
I'm not very fond of the 2560 boards; the chip itself is overpriced for its capabilities.
There are the 3rd party 1284-based boards, and the ARM boards to consider...
Logged

Pages: [1]   Go Up
Jump to: