Go Down

Topic: Code size with different versions and -flto optimization (Read 2987 times) previous topic - next topic


I am comparing sizes of the same code compiled with IDE022 and IDE 2.5.7.
Resuts using are difficult to interpret. I have anyhow seen that the sizes of the libraries it very different from one IDE to the other.
Adding all the calls that are relevant to Ehthernet library, for example, in 022 I get 6k while in 1.5.7  almost 9k:
I am sure this is due to greatest capability of the new libraries, but my scketch do not use any of those!
For example: I use a fixed IP and I find in the 1.5.7 a call  DNS::.......... that is taking 1k+ of memory!
There is any way to avoid these calls?


I don't think so.
The Ethernet library has been updated a lot. There were troubles with it in the past.
I don't know how all the function in that library is connected together.
The same for the SD library.
The SD library and the Ethernet are the main memory monsters, I think you have to reduce code size from the other parts.

I am willing to test your sketch, did you publish it somewhere ? or you can send me personal message.


Peter I appreciated very much your efforts to reduce the size of my sketch!!
But I believe that there is a more general problem due to the size of the new libraries been much larger then the old ones.
I have done a test compiling the EthernetServer example (taken from ......0023/library/ethernet/examples with corrections Client->EthernetClient , Server->EthernetServer). This what get:
IDE0022 -> 5386 bytes
IDE1.5.7  ->  8752 bytes. with -flto optimisation
This explain the larger part of the difference on my EnelWebLogger.
I understand that the new library it is much better then the old one, but if you want to use Arduino Unos to create a weblogging device
ayou have to  use  Ethernet and Sd (again about 9K)  libraries and then  you have left very little flash memory for your sketch !

To keep alive Arduino Uno and Arduino Ethernet boards I believe that some effort to reduce the size of SD and Ethernet libraries should be done.


I agree. That is how it is.
A small Ethernet and SD library would be very hard. Those libraries got bigger because of improvements and bug fixes.

Do you know what you are going to do ?


I have done the same exercise with SD library.
I have Compiled Datalogger example, with 1.5.7 and 0022 .
This time I obtain the opposite: the newest Sd library is 1k smaller:

Datalogger example compiled size
IDE 1.5.7 > 11800 bytes
IDE0022>12600 bytes

It is interesting to know it!! May be something on Ethernet library could be done......

For time being, I keep using old IDE for those sketches I have build for the UNO and Ethernet boards.
For new development I will likely use the mega or some of these new boards : I am interested to understand if the Due board can be updated with an ethernet interface.
I have already a more complex application developed on one Mega with the Ethernet shield  : it work well but the hardware is 3 time more espensive!
Basically the idea was to have a net of Arduinos , each with his own function (powerlogger, sprikler control, thermostatic controller, pool controller etc.) .
I hope to do most of those functions with an Arduino Ethernet board!


The story is not over...............

I have studied in comparaison the old and the new Ethernet libraries.
It is evident that the memory overhead is due to the new possibility of using DNS & DHCP.
This is something  not always used (in my case e.g.)  but the memory is always taken.
I have spent sometime cutting away parts of the new library :



That is a very good result  :P
The DCHP was added indeed. I forgot about that.
The library should have an option or so for a minimal version.


I will work more on the Ethernet library:
the way I want to do it is to insert a #define NODNS_DHCP if I have an sketch that dont need DNS/DHCP.
This way I can put a conditional compilation (#ifdef NODNS_DHCP) for the parts that can be excluded.

I will appreciate to have some comment/ guidance to this modification by somebody more expert than me!


Stiil struggling to reduce the size of the Ethernet library....
My understanding on how total size of linked core is build by Gcc linker is that, with --ffunction section flag, the sections that are not used are discarted : therefore if one doesnt use DHCP the relative DHCP library should not occupy memory.
But this is not the case : you have to manually take out those library parts and you obtain  a final code 3k smaller.
The compiler linker optimisation doesnt work in this case : so I have tryied to look deeper on why the DHCP is not discarted.
It appear that the call is coming from a lib function (Ethernet.begin() that is used in one form to get the address from DHCP.
Probably the compiler is not smart enougth to understand that I am not using that form and therefore include also the DHCP lib.
There may be way of solving this problem (with function attributes or gcc flags ) but I dont have enougth knowledge to do this.

May be the simplest solution is to rename the function Ethernet.begin Ethernet.beginDHCP :in that case the linker should automatically discart the DHCP library. But this will create a different Ethernet user interface.



The Arduino settings already discards unused function, both in the sketch and in the libraries.

The "Ethernet.begin()" can omit the IP parameter, which turns DHCP on.
If you look at this: http://github.com/arduino/Arduino/blob/master/libraries/Ethernet/Ethernet.cpp
Every "begin()" function calls the common "begin()", except the first one, and that one calls "beginWithDHCP()".
If that "begin()" is not used, the linker should not use the "beginWithDHCP()", so I think the DHCP must be linked in somehow somewhere else.

Two functions like Ethernet.begin() and Ethernet.beginDHCP() will solve it. But those two functions already exist, even though they are both called "begin()".


Sep 06, 2014, 11:11 am Last Edit: Sep 06, 2014, 11:20 am by pbecchi Reason: 1
Yes, yes: it is exactely as you are saying.
But , the code reduction I have obtained is simply due to commenting out the few lines of Ethernet lib with the code for the
.begin(mac_ad) case used to get IP from DHCP. As you can see:
Code: [Select]

#ifndef NODNS_DHCP
int EthernetClass::begin(uint8_t *mac_address)
  static DhcpClass s_dhcp;
  _dhcp = &s_dhcp;

  // Initialise the basic info

  // Now try to get our config info from a DHCP server
  int ret = _dhcp->beginWithDHCP(mac_address);
  if(ret == 1)
    // We've successfully found a DHCP server and got our configuration info, so set things
    // accordingly
    _dnsServerAddress = _dhcp->getDnsServerIp();

  return ret;

Therefore the compiler is not smart enoght to understand that I am not using that part probably because it does not understand the difference between .begin(mac_ad,IP_ad) and .begin(mac_ad).


Recently I wrote a build script for Cosa (an object-oriented framework for the Arduino). This allows scripting build of all the Cosa example sketched (over 150) and collecting size statistics.

Cosa can be built with both 1.5.7 and 1.0.5. Below are links to the log from the respective build.

The scripts are in the Cosa/build directory and named "cosa" and "tutto".



I have studied in comparaison the old and the new Ethernet libraries.
It is evident that the memory overhead is due to the new possibility of using DNS & DHCP.


Good job!  And thanks for informing us of the results.


I have modified the Ethernet Library with the addition of New.h file that contain definition of NODNS and NODNS_DHCP:

#define NODNS
#define NODNS_DHCP

The  code contain a conditional jump( #ifndef.....#endif) that remove the code relevant to dns and dhcp calls.
I have tested various library examples and the maximum saving is obtained defining bothh NODNS and NODNS_DHCP.
In that case all UDP library calls are remouved and the total reduction is about 3k :
the Library get back to the size of the old one (IDE <1.0.5).
Most of the examples relative to Ethernet Server applications get that redution.
When UDP library or DNS client application are specifically called by the example code the New.h file will have to be deleted:

//#define NODNS
//#define NODNS_DHCP

Otherwise the compiler linker will give errors. Obviously there will not be any size reduction in those cases.


An update to the -flto option : It fails !

My sketch on my Arduino Mega 2560 board was growing, and it is now : 53.012 bytes (20%) of program storage space and global variables use 2.034 bytes (24%) of dynamic memory.

Compiling with the -flto option causes this error : arduino-1.5.8/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/lib/avr6/libm.a(addsf3.o): In function `__addsf3': (.text.avr-libc.fplib+0x8): relocation truncated to fit: R_AVR_13_PCREL against symbol `__fp_round' defined in .text.avr-libc.fplib

That error is much longer, because it keeps going on. As far as I can tell, the optimization for some addresses is out of reach.

I was using the -flto option for a while, and I depend on it for other projects. So I would like to get it to work for the sketch for the Mega 2560 board as well.
Anyone knows how to fix this ?

Go Up