Interesting sketch size with unsigned longs

Hello,
Been trying to reduce my sketch size for past couple days, and I noticed really interesting thing with unsigned longs, but cannot figure out what is actually happening. I had these two lines in my code:

if(byteDoorsOpened) ulLightTurnOffTime += LIGHT_TURN_OFF_TIME;
else ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;

Variable types: byteDoorsOpened - uint8_t, ulLightTurnOffTime - uint32_t. Now with these two lines in my code, sketch is using 19913 bytes. I modified my code so now I only need this one line:

ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;

Now sketch is using 19865 bytes, that's 48 bytes lesser, nice. So I thought why the heck ulLightTurnOffTime += LIGHT_TURN_OFF_TIME uses ~40 bytes (assuming few bytes is used for if statement), therefore, just for the interest, I tried to write same incrementing line without if statement, like this:

ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;
ulLightTurnOffTime += LIGHT_TURN_OFF_TIME;

Surprisingly, sketch size was reduced by 2 bytes, now it's using only 19863 bytes. So now I'm wondering, why adding one more line of code reduces sketch size by 2 bytes, but writing them with if else statements, it increases sketch size by 48 bytes?

Your description is quite confusing. Please post complete sketches that illustrate your observation

#define LIGHT_TURN_OFF_TIME	15000

namespace DoorLights {

	uint8_t byteOldDoorState = 0;

	// Timer for turning lights off
	uint32_t ulLightTurnOffTime = 0L;

	void updateDoorState(uint8_t newState)
	{
		bool doorOpened = false;

		// Front left doors
		if((newState & DOOR_FL_OPEN) == DOOR_FL_OPEN && (byteOldDoorState & DOOR_FL_OPEN) == 0){
			doorOpened = true;
			turnOnLamp();
		}

		if(doorOpened){
			ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;
		}

		if(millis() >= ulLightTurnOffTime){
			turnOffLamp();
		}
		
		byteOldDoorState = newState;
	}

}

Your definition of a complete sketch and mine are obviously different

look at assembly, compiler works in mysterious ways

1 Like

i get the results shows in the code below

it shouldn't be surprising that eliminating the if statement simplifies and reduces the size of the code. it's not a matter of lines, but what those lines are coded to do.

i don't see a difference between the 2 lines w/o the if statements and the 1 line. the compiler can optimize the code to perform one addition, 2 * LIGHT_TURN_OFF_TIME, instead of doing 2 additions

# define LIGHT_TURN_OFF_TIME    100L

bool byteDoorsOpened;
unsigned long ulLightTurnOffTime ;

void setup() {
#if 0
    // 490 / 13     Prog/RAM
    if (byteDoorsOpened)
        ulLightTurnOffTime += LIGHT_TURN_OFF_TIME;
    else
        ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;
#elif 0
    // 466 / 9     Prog/RAM
    ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;
#else
    // 466 / 9     Prog/RAM
    ulLightTurnOffTime = millis() + LIGHT_TURN_OFF_TIME;
    ulLightTurnOffTime += LIGHT_TURN_OFF_TIME;
#endif
}

void loop() {
}
1 Like

Yeah, I took a look at assembly output, and things got more clear. I'm not familiar with AVR assembly, and never knew how 32-bit variables works in 8-bit CPU :grinning_face_with_smiling_eyes:, but now I understood that it takes 4 load instructions to load 32-bit variable into register, which uses 16 bytes of storage space, same for storing 32-bit value from register to variable, thus 32 bytes in total.

Code with if-else statement loads and stores ulLightTurnOffTime variable one more time, plus instructions for if-else statement and I guess that's where I'm loosing 48 bytes of program storage space.

For the code with 2 lines w/o the if-else statement, you explained that exactly as I saw it in assembly code, it just adds 30000 instead of 15000.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.