[Bug libstdc++/56861] std::vector::reserve optimization bug

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Dec 11 23:09:00 GMT 2015


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56861

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|WAITING                     |UNCONFIRMED
     Ever confirmed|1                           |0

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This is the testcase, without the Boost dependency. Compile with -std=c++11.
Define RESERVE or RESERVE_PLUS_ONE to change the behaviour.

I can't reproduce any significant difference in performance using 4.7.4 or
trunk. The time is surely bound by the std::find_if calls and I/O on the file
(which fails unless the file already exists btw, because you use std::fstream
not std::ofstream).

I don't see any bug here, or anything that needs fixing.


#include <algorithm>
#include <array>
#include <cstdint>
#include <vector>
#include <random>
#include <string>
#include <iostream>
#include <fstream>
#include <chrono>

namespace {
constexpr size_t array_size = 1;

unsigned number() {
        static std::random_device rd;
        static std::mt19937 random_engine(rd());
        static std::uniform_int_distribution<uint32_t> distribution(0,
std::numeric_limits<uint32_t>::max());
        return distribution(random_engine);
}

class Class {
        public:
                Class() {
                        x[0] = number();
                }
                std::string to_string() const {
                        return std::to_string(x[0]);
                }
                inline friend bool operator<=(Class const & lhs, Class const &
rhs) {
                        return lhs.x[0] <= rhs.x[0];
                }
        private:
                std::array<uint32_t, array_size> x;
};

template<typename Container>
void add(Container & container, Class const & value) {
        auto const it = std::find_if(std::begin(container),
std::end(container), [&](Class const & c) {
                return value <= c;
        });
        container.emplace(it, value);
}

// Do something with the result
template<typename Container>
void insert_to_file(Container const & container) {
        std::fstream file("file.txt");
        for (auto const & value : container) {
                file << value.to_string() << '\n';
        }
}

template<typename Container>
void f(std::vector<Class> const & values) {
        Container container;
#if defined RESERVE
        container.reserve(values.size());
#elif defined RESERVE_PLUS_ONE
        container.reserve(values.size() + 1);
#endif
        for (auto const & value : values) {
                add(container, value);
        }
        insert_to_file(container);
}

}

int main(int argc, char ** argv) {
        std::size_t const size = (argc == 1) ? 1 : std::stoul(argv[1]);
        // Default constructor of Class fills in values here
        std::vector<Class> const values_to_be_copied(size);
        typedef std::vector<Class> Container;
        auto start = std::chrono::system_clock::now();
        f<Container>(values_to_be_copied);
        auto finish = std::chrono::system_clock::now();
        std::cerr << "Finished in " <<
std::chrono::duration_cast<std::chrono::duration<double>>(finish -
start).count() << " seconds.\n";
}


More information about the Gcc-bugs mailing list