views:

51

answers:

3

I am kind of startled, especially after reading this.

I use

template <class T>
int GetPosition(vector<T> mVec, T element)
{
    return find(mVec.begin(), mVec.end(), element) - mVec.begin();
}

and

template <class T>
int GetPosition(map<T, int> mMap, T element)
{
    return mMap.find(element)->second;
}

as template functions to get the index of a specific element in my vector respectivly list.

Elements are unique pointers to objects, of which i want to retrieve the index off.

I then use this template in a for-loop like

for(int i = 0; i < myCount; i++)
{
  index = GetPosition(myVector, elements[i]) //or GetPosition(myMap, elements[i])
}

While all bits of information i gathered suggested to use a map, the map implementation is several orders of magnitude slower: 57 ms using the vector variant in comparision 70000ms using the map.

Something is severly borked here, but i do not know what. Do you?

Development plattform is MS VS 2008 Standard sp1, on windows XP

+3  A: 

Note, as your code is written here, you are passing both the vector and the map by value, i.e., you are rebuilding new copies of each on every call. That's clearly overwhelming the time of the search.

try:

template <class T> 
int GetPosition(const map<T, int> &mMap, T element) 
James Curran
+3  A: 

Since you are passing them by value, you are coping the vector and map in every call you are making. I'd sat that this makes the results pretty much meaningless.

Pass them as reference or const reference and run the test again.

template <class T>
int GetPosition(const vector<T>& mVec, T element)
{
    return find(mVec.begin(), mVec.end(), element) - mVec.begin();
}

template <class T>
int GetPosition(const map<T, int>& mMap, T element)
{
    return mMap.find(element)->second;
}
shoosh
Thank you. That reduces the lookup cost to barely nothing (6 ms for my testcase) in both cases. Now that was one exceptionally stupid mistake of mine ;)
sum1stolemyname
A: 

Aside from using references to avoid copies as the other answers mention, there's also a difference in algorithmic complexity here.

Look-up in (non-sorted) vector of size n has O(n) time complexity, whereas the same operation on the map has O(log n) time complexity.

Simply explained, it means that looking up an object in your vector takes time K1*n while it takes K2*log(n) time for the map, where K1 and K2 are some constants that depend on the implementation of the vector and map.

Which is faster in practice depends on the size of your container and what the constants are (I think it's safe to say K1will be faster.

Things like cache coherence will also come into play here, if your container is small everything will be in the cache for the vector but not for map. (With a cache, the constants won't really be constant either, but that's another story...)

Staffan
I recommend that you pick up an introductory computer science book to learn stuff things like Big O notation and basic data structures and algorithms. The biggest performance benefits comes from choosing the right algorithm and data structures; you're doomed to write suboptimal code if you don't have a good grasp of the basics in computer science.
Staffan
Lookup on a sorted list is O(lg N). Lookup on a map is supposed to be O(1), not O(lg N), though it degrades if your hash function causes collisions.
Ben Voigt
For a *hash* map look-up time is amortized O(1), yes. For a std::map it's O(log n). See e.g. this http://www.sgi.com/tech/stl/SortedAssociativeContainer.html
Staffan
@staffan I know about the different lookup speeds maps and vectos are suposed to have. They are the reason why i asked my question in the first place, since i didn't understand why the map lookup seemed to perform worse.
sum1stolemyname