# Sketch size quadruples when adding one line of code.

I’m trying to make a simple light that will respond to potentiometer.

However, when I add the line “ledVal[1] = 0;” to the code, the size increases from 226 bytes to 1152 bytes!

This is the code:

#define minimum 130
#define nominal 190
#define maximum 250
#define runs 64

uint8_t check, x, ledVal[5];
float analog;

void setup() {
DDRB = 7;
ledVal[0] = 63;
ledVal[1] = 10;
ledVal[2] = 100;
}

void loop() {
while (1){
analog = 0;
for (int i=0;i<runs;i++) analog = analog + x;
analog = analog / runs;
analog = analog * 1.07421875;

if(analog < minimum){
ledVal[0] = 128;
ledVal[1] = 0;
}
}
}

if you would remove the said line from the code, you could see for yourself…

Why does this happen…?

while (1){ This while loop is pointless that's what loop does.

As for the size increase - so what it not a problem is it!. But most likely the compiler has seen some code worth keeping and no optimssied it away.

Mark

for (int i=0;i<runs;i++) analog = analog + x;

What does this accomplish? x is never set to anything but 0. So you add 0 to a number a whole bunch of times? What use is that?

Would have been usefull to tell, i’m using an attiny13, with only 1024 bytes ram…

The x value is where i’ll have it read an analog pin, but i’m not that far yet, and the sketch is already too big this way…

holmes4:
while (1){ This while loop is pointless that’s what loop does.

I always use this, it’s 10 clock cycles faster, and actually makes the sketch 14 bytes smaller.

get rid of the floating point variable and you cut the size by half. Floating point is expensive. You're multiplying by something that is really close to 1. Are you sure you can't use integer types here?

I cannot see it happening on my Uno. In theory you have assigned a simple legal variable - hence memory, and if it is uninitialized it should not change the memory assigned / allocated. But compilers are not perfect and my guess is you got something else it does not like and it is not going to tell you what it is. It will show up somewhere else soon. Cheer up Vaclav

I dumped out all the floats, i'm at about 600bytes now! :D I'll have to rework a lot of the math I was going to do in floats though, but i'll think it's going to work like this. :)

Thanks a lot!

The IDE reports the size of the code NOT the data space. Its not telling you how much of the RAM you have used.

Mark

The IDE reports the size of the code NOT the data space.

And the code size does indeed change, though I've got less than 3:1 with IDE 1.0.5 Time to examine the generated code.

AWOL: And the code size does indeed change, though I've got less than 3:1 with IDE 1.0.5

What kind of values do you get? Are you using a Uno as specified board?

Are you using a Uno as specified board?

Yup.

1420 vs. 500 bytes.

Well, I managed to get it working without the floats!

I'm still baffled though, I can't think of anything why this would happen..

With the “ledVal[1] = 0;” commented out, the compiler optimizes away almost all of the loop() function:

000000be <loop>:
be:   80 e0           ldi     r24, 0x00       ; 0
c0:   90 e0           ldi     r25, 0x00       ; 0
c2:   01 96           adiw    r24, 0x01       ; 1
c4:   80 34           cpi     r24, 0x40       ; 64
c6:   91 05           cpc     r25, r1
c8:   e1 f7           brne    .-8             ; 0xc2 <loop+0x4>
ca:   f9 cf           rjmp    .-14            ; 0xbe <loop>

All the analog code (and libraries) are omitted. Essentially you have nonsense code that doesn’t do anything, and the compiler produces small code that (equally) does nothing.

For some reason, adding the ledVal[1] statement defeats this optimization, so all that math gets done, and the FP library code gets included. I don’t have any theory as to WHY this causes the optimization to be defeated.

It is generally dangerous, in this day of optimizing compilers, to try to get a size estimate for a program that isn’t actually doing anything…

(This doesn't seem to happen with a newer version of the compiler. Very Odd.)

This:

void setup() {
DDRB = 7;
ledVal[0] = 63;
ledVal[1] = 10;
ledVal[2] = 100;
}
void loop() {
while (1){
analog = 0;
for (int i=0;i<runs;i++) analog = analog + x;
analog = analog / runs;
analog = analog * 1.07421875;

if(analog < minimum){
ledVal[0] = 128;
}
}
}

Becomes:

DDRB = 7;
ledVal[0] = 63;
ledVal[1] = 10;
ledVal[2] = 100;
...
while (1){
analog = 0;
for (int i=0;i<runs;i++) analog = 0 + 0;
analog = 0 / 64;
analog = 0 * 1.07421875;

if(0 < 130){
ledVal[0] = 128;
}
}
}

Which becomes:

DDRB = 7; //must perform as DDRB is volatile
// ledVal[0] = 128; //not used so optimised away
// ledVal[1] = 10; //not used so optimised away
// ledVal[2] = 100; //not used so optimised away
...
while (1){
//   analog = 0; //never used
for (int i=0;i<runs;i++) ; //for loop not removed as it acts as a delay?
//    analog = 0 / 64; //optimised away as 0/anything = 0
//    analog = 0 * 1.07421875; //again, pointless
//    if(0 < 130){ //always true
//      ledVal[0] = 128; //result is never used
//    }
}
}

Thus you now have:

DDRB = 7; //must perform as DDRB is volatile
while (1){
for (int i=0;i<runs;i++) ; //for loop not removed as it acts as a delay?
}
}

Which is much smaller than what was there before, but is functionally the same.

As to why adding the ledVal[1]=0 makes a difference, I can only assume that it is a glitch which causes gcc to not optimise away all the useless code.

I ran into some more odd problems, like my code shrinking down to half it's size, when changing an = to a +=. The program also stopped functioning after this.

This was genuinly weird, so I tried the code on a Uno, same problem, so something really weird had to be going on.

The problem ended up being the extra while loop I added (to save those 10 precious clockcycles), after removing this, the code always compiled to the correct (large) amount of bytes.

I still don't really get what was going on, except for that the compiler optimized out all my code, but at least know where it came from. :)