[Bug libstdc++/109022] New: Low performance of std::map constructor for already sorted data of std::pair
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109022 Bug ID: 109022 Summary: Low performance of std::map constructor for already sorted data of std::pair Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: marekr22 at wp dot pl Target Milestone: --- Performance of constructor accepting iterators to sorted data of std::pair is much lower then inserting same data for std::pair (matches value_type of std::map). Here is benchmark showing the issue: ``` #include #include #include #include #include constexpr size_t DataSizeStart = 8 << 0; constexpr size_t DataSizeStop = 8 << 3; using TestData = std::vector>; using TestDataConst = std::vector>; std::string makeStringFor(size_t x) { std::ostringstream out; out << std::setfill('0') << std::setw(6) << x; return out.str(); } TestData sortedData(size_t n) { TestData r; r.reserve(n); size_t i = 0; std::generate_n(std::back_inserter(r), n, []() { return std::pair{makeStringFor(++i), i}; }); return r; } TestData shuffledData(size_t n) { auto data = sortedData(n); std::random_device rd; std::mt19937 g(rd()); std::shuffle(data.begin(), data.end(), g); return data; } TestDataConst sortedConstData(size_t n) { auto r = sortedData(n); return {r.begin(), r.end()}; } TestDataConst shuffledConstData(size_t n) { auto r = shuffledData(n); return {r.begin(), r.end()}; } template static void CreateMapInsert(benchmark::State& state) { auto n = state.range(0); auto data = Data(n); for (auto _ : state) { benchmark::DoNotOptimize(data); std::map m; for (auto& p : data) { m.insert(m.end(), p); } benchmark::DoNotOptimize(m); } } BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); // BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); // BENCHMARK(CreateMapInsert)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); template static void CreateMapDirectly(benchmark::State& state) { auto n = state.range(0); auto data = Data(n); for (auto _ : state) { benchmark::DoNotOptimize(data); std::map m{data.begin(), data.end()}; benchmark::DoNotOptimize(m); } } BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); // BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); // BENCHMARK(CreateMapDirectly)->RangeMultiplier(2)->Range(DataSizeStart, DataSizeStop); ``` Live demo gcc 12.2: https://quick-bench.com/q/H8lqugNgMG-sWQ6cKBsdB7EBRpU Note that CreateMapInsert performs best since it feeds to constructos to iterators to std::pair while CreateMapInsert performs badly (looks like time complexity is worse) adn only diffrence is that it provides iterators to std::. Same issue is observed for clang 14.0 and libstdc++: https://quick-bench.com/q/6VA3vRdKmqPEYrvTnFFla4gxwXk but it is not a problem on clang 14.0 and libc++: https://quick-bench.com/q/-S-lX3N8Y-8vL9CCl-5bW5jolWA here is result for sing size input data (easier to read): https://quick-bench.com/q/kbDOPA8PNZFfrzUH_-70cJgApeE Issue was observed when filing answer on https://stackoverflow.com/a/75535056/1387438
[Bug c++/102493] New: non-type template specialization for member pointer to field and function reports leads to unexpected conflict
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102493 Bug ID: 102493 Summary: non-type template specialization for member pointer to field and function reports leads to unexpected conflict Product: gcc Version: 11.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: marekr22 at wp dot pl Target Milestone: --- Here is minimum complete verifiable example (C++17): ```cpp #include #include #include template struct field_type; template struct field_type { using type = R; }; template struct field_type { using type = R; }; template using field_type_t = typename field_type::type; class Foo { public: int x = 0; double y = 0; std::string s; const int cx = 0; Foo() = default; void bar() { std::cout << "bar\n"; } int par(int z) { std::cout << "bar\n"; return z; } }; template constexpr bool test = std::is_same_v, T>; static_assert(test<::x,int>, ""); static_assert(test<::cx, const int>, ""); static_assert(test<::s,std::string>, ""); static_assert(test<::y,double>, ""); #ifndef HIDE_PROBLEM_ON_GCC_11 static_assert(test<::bar, void>,""); static_assert(test<::par, int>, ""); #endif ``` This compile on all compilers https://godbolt.org/z/31svobz3z except for gcc 11.1 and 11.2 (gcc 10.3 works). Reported error is: ``` : In substitution of 'template using field_type_t = typename field_type::type [with auto FP = ::bar]': :44:28: required from 'constexpr const bool test<::bar, void>' :51:15: required from here :21:7: error: ambiguous template instantiation for 'struct field_type<::bar>' 21 | using field_type_t = typename field_type::type; | ^~~~ :9:8: note: candidates are: 'template struct field_type [with R = void(); T = Foo; R T::* FP = ::bar]' 9 | struct field_type |^~ :15:8: note: 'template struct field_type [with R = void; T = Foo; Args = {}; R (T::* FP)(Args ...) = ::bar]' 15 | struct field_type |^~ :21:7: error: invalid use of incomplete type 'struct field_type<::bar>' 21 | using field_type_t = typename field_type::type; | ^~~~ :6:8: note: declaration of 'struct field_type<::bar>' 6 | struct field_type; |^~ ```
[Bug c++/98798] New: Custom operator new[] and delete[] is buggy for aligned class
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98798 Bug ID: 98798 Summary: Custom operator new[] and delete[] is buggy for aligned class Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: marekr22 at wp dot pl Target Milestone: --- Basically when class has alignment requirement and custom operators `new[]` and `delete[]` (C++17), then address sanitizer reports buffer overflow: ## MCVE: ```cpp #include #include class EndlineOnDone { std::ostream& out; public: EndlineOnDone(std::ostream& out) : out{out} {} ~EndlineOnDone() { out << std::endl; } std::ostream& stream() { return out; } }; #define VAR(x) " " #x "=[" << x << "]" #define LOG EndlineOnDone(std::cout).stream() << __PRETTY_FUNCTION__ std::ostream& operator<<(std::ostream& out, std::align_val_t a) { return out << static_cast(a); } class alignas(32) Foo { public : double x, y, z; void * operator new (size_t s, std::align_val_t a) { auto p = aligned_alloc(static_cast(a), s); LOG << VAR(p) << VAR(s) << VAR(a); return p; } void operator delete (void * p, size_t s, std::align_val_t a) { LOG << VAR(p) << VAR(s) << VAR(a); if (p) free(p); } #if 1 void * operator new[ ] (size_t s, std::align_val_t a) { auto p = aligned_alloc(static_cast(a), s); LOG << VAR(p) << VAR(s) << VAR(a); return p; } void operator delete[ ] (void *p, size_t s, std::align_val_t a) { LOG << VAR(p) << VAR(s) << VAR(a); if (p) free(p); } #endif }; int main() { { LOG << " std::make_unique"; auto p = std::make_unique(); } { LOG << " std::make_unique"; auto p = std::make_unique(3); } } ``` https://godbolt.org/z/7xd8YM ## gcc logs (no address sanitizer): ```txt int main() std::make_unique static void* Foo::operator new(size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32] static void Foo::operator delete(void*, size_t, std::align_val_t) p=[0x21d6ec0] s=[32] a=[32] int main() std::make_unique static void* Foo::operator new [](size_t, std::align_val_t) p=[0x21d6f40] s=[96] a=[32] static void Foo::operator delete [](void*, size_t, std::align_val_t) p=[0x21d6f40] s=[3616] a=[32] ``` Note that `s` value for `Foo[]` doesn't match for `new[]` and `delete[]` operations. Address sanitizer reports buffer overflow. clang is fine (didn't check msvc). ## Workaround Adding explicit destructor `~Foo() {}` fixes this issue: https://godbolt.org/z/WoM91Y (use of `~Foo() = default;` doesn't fix it). https://stackoverflow.com/q/65826663/1387438