Darryl Gove's blog
Doctor Who exhibition in Coventry
We've recently returned from a vacation in the UK. We had a fun time, the kids got dragged around all sorts of entertainments. One thing I did manage to squeeze in was a trip to the Doctor Who exhibition in Coventry. It took us about forty minutes to wander through, and look at the props from the show. It's a temporary show being held at the Coventry Transport Museum, so after lunch we wandered through that. The transport museum had some interesting vehicles - a De Lorean, Thrust II, and Thrust SSC. A grand day out.
Posted at 10:37PM Aug 29, 2009 by Darryl Gove in Personal |
Maps in the STL
I was looking at some code with a colleague and we observed a bunch of time in some code which used the std::map to set up mappings between strings. The source code looked rather like the following:
#include <map>
#include <string>
using namespace std;
int func(map<string,string>&mymap, string &s1, string &s2)
{
mymap.insert(pair<string,string>(s1,s2));
return 0;
}
When compiled with CC -O -c -library=stlport4 map.cc this expands to a horrendous set of calls, here's the first few:
$ er_src -dis func map.o|grep call
[?] 188d: call std::basic_string...::basic_string
[?] 189f: call std::basic_string...::basic_string
[?] 18b2: call std::basic_string...::basic_string
[?] 18c2: call std::basic_string...::basic_string
[?] 18d8: call std::_Rb_tree...::insert_unique
[?] 18f8: call std::__node_alloc...::_M_deallocate
[?] 190c: call std::_STLP_alloc_proxy...::~_STLP_alloc_proxy
...
What's happening is that the act of making a pair object is causing copies to be made of the two strings that are passed into the pair constructor. Then the pair object is passed into the insert method of std::map and this results in two more copies of the strings being made. There's a bunch of other stuff going on, and the resulting code is a mess.
There's an alternative way of assigning the mapping:
#include <map>
#include <string>
using namespace std;
int func(map<string,string>&mymap, string &s1, string &s2)
{
mymap[s1]=s2;
return 0;
}
When compiled the resulting code looks a lot neater:
$ er_src -dis func map.o|grep call
[?] 28e6: call std::map...::operator[]
[?] 2903: call std::basic_string...::_M_assign_dispatch
Of course a neater chunk of code is nice, but the question is whether the code for ::operator[] contains the same ugly mess. Rather than disassembling to find out, it's simpler to time the two versions and see which does better. A simple test harness looks like:
int main()
{
map<string,string>mymap;
string s1,s2;
long long i;
s1="123456789";
s2="987654321";
for (i=0; i<100000000; i++)
{
func(mymap,s1,s2);
}
}
It's a less than ideal harness since it uses constant strings, and one version of the code might end up bailing early because of this. The performance of the two codes is quite surprising:
real 6.79 user 6.77 sys 0.00 real 1:03.53 user 1:03.26 sys 0.01
So the version that creates the pair object is about 10x slower!
Posted at 09:57AM Aug 28, 2009 by Darryl Gove in Sun | Comments[4]
Second life talk audio available.
The slides, transcript, and audio from my Second Life talk about The Developer's Edge are now available.
Posted at 09:30AM Aug 28, 2009 by Darryl Gove in Sun |


