Search code examples
c++performancealgorithmmemorymemory-efficient

Small repeated arithmetic vs creating new variables


I am writing in C++ for a low-spec device (~3MB RAM, ~70MHz CPU) and I am wondering which will run more efficiently (And by how much). This is a simplified segment of code that will run 120-600 times a second:

void checkCollisions(int x, int y)
{
    int p1x = x, p1y = y+2;
    int p2x = x, p2y = y+3;
    int p3x = x+3, p3y = y+3;
    // And so on...

    if (wallAt(p1x-1, p1y) || wallAt(p2x-1, p2y))
        setCollision(LEFT, true);
    if (wallAt(p1x, p1y) || wallAt(p4x, p4y) || wallAt(p5x, p5y))
        inGround = true;
    else
        inGround = false;
    // And so on...
}

Or replacing the integers with their definitions:

void checkCollisionsAlt(int x, int y)
{
    if (wallAt(x-1, y+2) || wallAt(x-1, y+3))
        setCollision(LEFT, true);
    if (wallAt(x, y+2) || wallAt(x+3, y) || wallAt(x+2, y))
        inGround = true;
    else
        inGround = false;
    // And so on...
}

Here's a diagram of the example:

Example Diagram

The first one is more understandable, but I would expect uses more memory. How much of a difference does it make?


Solution

  • A few points to think about:

    1. If the full version also doesn't have any recursion, you can worry less about the variables(p1x etc.) on the stack.
    2. Stack-consumption is ephemeral and shouldn't hit you unless you have pathological code, such as deep recursion with each frame being heavy.
    3. Recursion usually is a bad idea with a tight memory budget.
    4. The fact that you have them as explicitly named variables, does not mean they will be so at the execution time.
    5. Any decent compiler is likely to recognize the life-time of the variables and push them to registers. Please verify this with the compiler optimization level that you are currently using and consider bumping it up, if needed.

    Also, what is the expected range of these values of p1x etc. Why not use short int?

    Ephemeral nature of the stack memory growth means that your peak heap memory is not impacted. Stack can grow and shrink and depending on the lay out and amount budgeted for stack, you might not have to worry about this at all.

    Note: Any and ALL heap allocations need to be carefully vetted. Try implementing a custom allocator, rather than incurring the standard malloc() chunk overheads. Of course, you didn't bring up the heap in the question, but, just a thing to keep in mind.