C++ Hashtable container performance
890486Nov 1 2011 — edited Nov 23 2011I found interesting behaviour of C++ Hashtable container.
To demonsteate this, let’s cosider the following example:
We have got 100 000 of keys and values that we will be adding to Hashtable and measure how long it takes.
Both key and value are plain C string (char*). Please see source code bellow in the post.
In the degug build I am getting following output
Adding to map 100000 items took 1.469 seconds
Adding to map 100000 items took 1.954 seconds
Adding to map 100000 items took 1.954 seconds
Adding to map 100000 items took 1.954 seconds
Adding to map 100000 items took 1.953 seconds
Adding to map 100000 items took 1.953 seconds
Adding to map 100000 items took 1.969 seconds
In the release build I am getting the following
Adding to map 100000 items took 1.359 seconds
Adding to map 100000 items took 2.766 seconds
Adding to map 100000 items took 2.687 seconds
Adding to map 100000 items took 2.719 seconds
Adding to map 100000 items took 2.718 seconds
Adding to map 100000 items took 2.719 seconds
Adding to map 100000 items took 2.718 seconds
Adding to map 100000 items took 2.735 seconds
My question here – why debug build performs significantly better then release?
There is another interesting thing here:
Let’s comment out the following line
coherenceMap->clear();
Now debug build produces a following lines:
Adding to map 100000 items took 1.5 seconds
Adding to map 100000 items took 1.422 seconds
Adding to map 100000 items took 1.422 seconds
Adding to map 100000 items took 1.421 seconds
And release
Adding to map 100000 items took 1.328 seconds
Adding to map 100000 items took 1.25 seconds
Adding to map 100000 items took 1.25 seconds
Adding to map 100000 items took 1.282 seconds
Adding to map 100000 items took 1.265 seconds
Now release builds as expected performs better then debug one.
Why removing all elements from map causing such performance degradation in release build?
This is synthetic example to demonstrate a problem. In my real application permanence difference even more dramatic 6 seconds in release builds vs 1.3 seconds in debug build.
I think poor performance of release builds relates to the calling of coherenceMap->clear() method. First batch of 100 000 gets added in 0.5 seconds and following(after coherenceMap->clear() called to remove previous elements) take 5-6 seconds.
Is it a known issue or can some one try my test application and confirm or reject my findings.
I am on Windows XP, Coherence 3.6 and Visual Studio 2005.
Test application source code
// CPPCoherenceTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <map>
#include <sstream>
#include <iostream>
#include<ctime>
#include<windows.h>
#include "TopicSnapReader.h"
#include "TopicSnap.h"
using namespace coherence::lang;
using coherence::net::CacheFactory;
using coherence::net::NamedCache;
using coherence::util::extractor::ReflectionExtractor;
using coherence::util::ValueExtractor;
using coherence::util::extractor::PofExtractor;
using coherence::util::filter::EqualsFilter;
using coherence::util::Filter;
using coherence::util::Iterator;
using coherence::util::extractor::KeyExtractor;
using coherence::util::Hashtable;
using coherence::util::HashSet;
std::map<std::string, std::string> testDataMap;
int snapSize = 100000;
char **keys;
char **values;
void generateTestData()
{
keys = new char*[snapSize];
values = new char*[snapSize];
std::stringstream strStream;
for (int i = 0; i < snapSize; ++i)
{
strStream.str("");
strStream << "key-" << i;
std::string key = strStream.str();
key.resize(250, '_');
strStream.str("");
strStream << "value-" << i;
std::string value = strStream.str();
value.resize(1024, '-');
keys[i] = new char[key.length() + 1];
strcpy(keys, key.c_str());
values[i] = new char[value.length() + 1];
strcpy(values[i], value.c_str());
}
}
int tmain(int argc, TCHAR* argv[])
{
HRESULT hr = CoInitializeEx( 0, COINIT_MULTITHREADED );
_ASSERT( SUCCEEDED( hr ) );
( hr );
generateTestData();
Map::Handle coherenceMap = Hashtable::create();
while (true)
{
coherenceMap->clear();
clock_t t1=clock();
for (int i = 0; i < snapSize; ++i)
{
coherenceMap->put(String::View(keys[i]), String::View(values[i]) );
}
clock_t t2=clock();
std::cout << "Adding to map " << snapSize << " items took " << double(t2-t1)/CLOCKS_PER_SEC << " seconds" << std::endl;
}
return 0;
}
Edited by: user2593443 on 01-Nov-2011 12:01