Bug 70898 - Stateful Compare objects are very slow
Summary: Stateful Compare objects are very slow
Status: RESOLVED DUPLICATE of bug 67085
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.8.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 70899 (view as bug list)
Depends on:
Blocks:
 
Reported: 2016-05-02 02:06 UTC by gccbugs
Modified: 2016-05-04 08:51 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description gccbugs 2016-05-02 02:06:02 UTC
/*

The following code is four times slower with libstdc++ than with libc++.

I think the problem is partially too many copies in stl_heap.h. Instrumenting the code with a copy constructor and a destructor shows two copies of a Comp and two destructions for every call to push, while in libc++ it's only one call to a copy constructor and one call to the destructor. It seems like zero calls should be sufficient, as the Compare object could be kept around between push calls and reused.

*/

#include <queue>
#include <vector>
#include <iostream>

using namespace std;

struct Comp {
  vector<int> data;
  Comp(int n) : data(n,n) {}
  bool operator()(const double &x, const double &y) const { return x < y; }                                                                                                                                                                    
};                                                                                                                                                                                                                                             

int main() {
  vector<double> data;
  Comp comp(150000);
  priority_queue<double, vector<double>, Comp> pq(comp, data);
  for (int i = 0; i < 100000; ++i) {
    pq.push(i);
  }                                                                                                                                                                                                                                            
  cout << pq.top() << endl;
}
Comment 1 gccbugs 2016-05-02 02:17:00 UTC
*** Bug 70899 has been marked as a duplicate of this bug. ***
Comment 2 Marc Glisse 2016-05-02 06:01:29 UTC
I think you are supposed to use std::reference_wrapper<Comp> as comparator if you don't want to copy it around. We did talk about reducing the number of copies (mostly in the context of sorting), but nobody has found the time / motivation to write patches.
Comment 3 Jonathan Wakely 2016-05-03 10:00:31 UTC
This is being tracked as PR 51965

*** This bug has been marked as a duplicate of bug 51965 ***
Comment 4 Marc Glisse 2016-05-03 10:08:30 UTC
(In reply to Jonathan Wakely from comment #3)
> This is being tracked as PR 51965

PR 51965 seems to be about extra copies of the values, while this one is more about extra copies of compare objects (then there are also extra copies of iterators).
Comment 5 Jonathan Wakely 2016-05-03 10:17:30 UTC
Ah, then it's a dup of PR 67085 (which I had incorrectly marked as a dup of 51965).

*** This bug has been marked as a duplicate of bug 67085 ***
Comment 6 gccbugs 2016-05-04 04:00:29 UTC
I'm not sure I agree that this is a duplicate. In particular, 67085 says that std::priority_queue operations "should not copy comparators". I suggested that as well in my initial report, but upon a closer reading of the standard, I'm not sure that would be conformant, since the standard requires priorityy_queue::push to call std::push_heap, and std::push_heap has to take its comparator by value.

On the other hand, I do think that copying comparators *fewer* times that libstdc++ currently does is permitted, and I think it could have a big performance benefit in some cases.

In particular, though push_heap seems like it must take the comparator by value, __push_heap is not required to do so. The constructor for __gnu_cxx::__ops::_Iter_comp_val and the function __gnu_cxx::__ops::__iter_comp_val also do not have to take their comparators by value.
Comment 7 Jonathan Wakely 2016-05-04 08:51:47 UTC
Right, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67085#c5

It's a dup. There's no point making two very similar changes to address very slightly different things.

*** This bug has been marked as a duplicate of bug 67085 ***