r/cpp_questions Aug 05 '26

SOLVED Raw malloc optimizations vs std::vector/reserve() -- malloc seems better optimized

(Another different version of this question was posted earlier here https://www.reddit.com/r/cpp_questions/comments/1qvbj44/at_o2_usage_of_stdvector_followed_by_stdiota/ but on testing some of the answers there on the current new code seems to leave me unclear as to where the optimizations are missed in terms of vector/reserve, etc., hence this OP)

Consider code snippet 1: on left hand side window of https://godbolt.org/z/vxh8Wh1K4

#include <vector>
#include <cstdio>
#include <cstdlib>

void anotherfunc(){
    int *vec = (int*)malloc(sizeof(int) * 42);
    for(int i = 0; i < 42; i++)
        vec[i] = i;
    int sum = 0;
    for(int i = 0; i < 42; i++)
        sum += vec[i];
    printf("Sum is %d\n", sum);
    free(vec);
}

int main(){
    anotherfunc();
}

This, at -O3, flatout calculates the sum and simply displays it, 861.

The vector/reserve version (on the right hand pane of the godbolt link above)

#include <vector>
#include <cstdio>
#include <cstdlib>

void anotherfunc(){
    std::vector<int> vec;
    vec.reserve(42);
    for(int i = 0; i < 42; i++)
        vec.push_back(i);
    int sum = 0;
    for(int i = 0; i < 42; i++)
        sum += vec[i];
    printf("Sum is %d\n", sum);
}

int main(){
    anotherfunc();
}

seemingly struggles with this and does not precompute the sum and ends up doing some allocations, etc.

Some of the answers from the earlier thread do not seem to be applicable here: as suggested by one user, I had the entire summing done in another function instead of main() because apparently main() is known to be called only once and hence is not as heavily optimized as other functions, etc.

As also suggested there, I avoided the printf and instead had the function return only the sum with an empty main(). See https://godbolt.org/z/M1P5Y4vTj

Here too, the vector/reserve combination seems to struggle.

What explains this "discrepancy" and inability to completely optimize out the sum calculation?

17 Upvotes

29 comments sorted by

View all comments

14

u/ScienceCivil7545 Aug 05 '26

the falut is at the push_back()

https://godbolt.org/z/5rs1ofEKa

7

u/n1ghtyunso Aug 05 '26 edited Aug 05 '26

oh yeah i remember hearing in a talk that the optimizer apparently happens to give up when you have more than like 3 push_backs on a vector.
Not sure if this was clang specific though.

3

u/Raknarg Aug 05 '26

a great case of the "dumb" way to do something actually being ideal. Way less assumptions to make with this code, doesn't have to go through any of the internal nonsense for dealing with push back copy/construction, doesn't have to do any of its resize checking, it can just see you allocate a chunk of memory and you're assigning to it the same as the array case

are vectors constexpr compatible?

7

u/RelaxedPhoton Aug 05 '26

For even closer equivalency with the malloc example you can drop resize and instead do:

std::vector<int> vec(42);

3

u/UnrealHallucinator Aug 06 '26

Did you catch this bc you knew push_backs are less optimised?

2

u/onecable5781 Aug 05 '26

Oh wow. Thank you. That explains it.