|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Апр 2, 2004 22:09:10 Истинным ассемблерщикам (на каком бы языке они не писали) всегда любопытна производительность того или иного клочка кода. Речь в данном топике пойдет об STL. Примеры взяты из "Thinking in C++" Bruce Ekkel. Сравнивался hash_map с map. Сравнивал на Windows и Solaris. Компилировал Visual Studio .NET 2003 и g++. Врубил всю оптимизацию, до которой только смог додуматься и дотянуться. Код:
//: C20:MapVsHashMap.cpp
// The hash_map header is not part of the
// Standard C++ STL. It is an extension that
// is only available as part of the SGI STL:
#include <hash_map>
#include <iostream>
#include <map>
#include <ctime>
using namespace std;
int main(){
hash_map<int, int> hm;
map<int, int> m;
clock_t ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
m.insert(make_pair(j,j));
cout << "map insertions: "
<< clock() - ticks << endl;
ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
hm.insert(make_pair(j,j));
cout << "hash_map insertions: "
<< clock() - ticks << endl;
ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
m[j];
cout << "map::operator[] lookups: "
<< clock() - ticks << endl;
ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
hm[j];
cout << "hash_map::operator[] lookups: "
<< clock() - ticks << endl;
ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
m.find(j);
cout << "map::find() lookups: "
<< clock() - ticks << endl;
ticks = clock();
for(int i = 0; i < 100; i++)
for(int j = 0; j < 1000; j++)
hm.find(j);
cout << "hash_map::find() lookups: "
<< clock() - ticks << endl;
} ///:~
Результат на Solaris (SPARC v9): map insertions: 170000 hash_map insertions: 80000 map::operator[] lookups: 130000 hash_map::operator[] lookups: 50000 map::find() lookups: 120000 hash_map::find() lookups: 40000 Результат на Windows (P4): map insertions: 15 hash_map insertions: 0 map::operator[] lookups: 16 hash_map::operator[] lookups: 0 map::find() lookups: 0 hash_map::find() lookups: 0 Результат в миллисекундах. Хи-хи, на солярные результаты сравнительно с виндой особо внимания не обращайте. У нас особые солярные машины 8-) А вообще, кто теперь скажет, что hash_map медленнее? Код по сравнению других STL-контейнеров:
//: C07:SequencePerformance.cpp
// Comparing the performance of the basic
// sequence containers for various operations
//{L} ../TestSuite/Test
#include <vector>
#include <queue>
#include <list>
#include <iostream>
#include <string>
#include <typeinfo>
#include <ctime>
#include <cstdlib>
using namespace std;
class FixedSize {
int x[20];
// Automatic generation of default constructor,
// copy-constructor and operator=
} fs;
template<class Cont>
struct InsertBack {
void operator()(Cont& c, long count) {
for(long i = 0; i < count; i++)
c.push_back(fs);
}
char* testName() { return "InsertBack"; }
};
template<class Cont>
struct InsertFront {
void operator()(Cont& c, long count) {
long cnt = count * 10;
for(long i = 0; i < cnt; i++)
c.push_front(fs);
}
char* testName() { return "InsertFront"; }
};
template<class Cont>
struct InsertMiddle {
void operator()(Cont& c, long count) {
typename Cont::iterator it;
long cnt = count / 10;
for(long i = 0; i < cnt; i++) {
// Must get the iterator every time to keep
// from causing an access violation with
// vector. Increment it to put it in the
// middle of the container:
it = c.begin();
it++;
c.insert(it, fs);
}
}
char* testName() { return "InsertMiddle"; }
};
template<class Cont>
struct RandomAccess { // Not for list
void operator()(Cont& c, long count) {
int sz = c.size();
long cnt = count * 100;
for(long i = 0; i < cnt; i++)
c[rand() % sz];
}
char* testName() { return "RandomAccess"; }
};
template<class Cont>
struct Traversal {
void operator()(Cont& c, long count) {
long cnt = count / 100;
for(long i = 0; i < cnt; i++) {
typename Cont::iterator it = c.begin(),
end = c.end();
while(it != end) it++;
}
}
char* testName() { return "Traversal"; }
};
template<class Cont>
struct Swap {
void operator()(Cont& c, long count) {
int middle = c.size() / 2;
typename Cont::iterator it = c.begin(),
mid = c.begin();
it++; // Put it in the middle
for(int x = 0; x < middle + 1; x++)
mid++;
long cnt = count * 10;
for(long i = 0; i < cnt; i++)
swap(*it, *mid);
}
char* testName() { return "Swap"; }
};
template<class Cont>
struct RemoveMiddle {
void operator()(Cont& c, long count) {
long cnt = count / 10;
if(cnt > c.size()) {
cout << "RemoveMiddle: not enough elements"
<< endl;
return;
}
for(long i = 0; i < cnt; i++) {
typename Cont::iterator it = c.begin();
it++;
c.erase(it);
}
}
char* testName() { return "RemoveMiddle"; }
};
template<class Cont>
struct RemoveBack {
void operator()(Cont& c, long count) {
long cnt = count * 10;
if(cnt > c.size()) {
cout << "RemoveBack: not enough elements"
<< endl;
return;
}
for(long i = 0; i < cnt; i++)
c.pop_back();
}
char* testName() { return "RemoveBack"; }
};
template<class Op, class Container>
void measureTime(Op f, Container& c, long count){
string id(typeid(f).name());
bool Deque = id.find("deque") != string::npos;
bool List = id.find("list") != string::npos;
bool Vector = id.find("vector") !=string::npos;
string cont = Deque ? "deque" : List ? "list"
: Vector? "vector" : "unknown";
cout << f.testName() << " for " << cont << ": ";
// Standard C library CPU ticks:
clock_t ticks = clock();
f(c, count); // Run the test
ticks = clock() - ticks;
cout << ticks << endl;
}
typedef deque<FixedSize> DF;
typedef list<FixedSize> LF;
typedef vector<FixedSize> VF;
int main(int argc, char* argv[]) {
srand(time(0));
long count = 1000;
if(argc >= 2) count = atoi(argv[1]);
DF deq;
LF lst;
VF vec, vecres;
vecres.reserve(count); // Preallocate storage
measureTime(InsertBack<VF>(), vec, count);
measureTime(InsertBack<VF>(), vecres, count);
measureTime(InsertBack<DF>(), deq, count);
measureTime(InsertBack<LF>(), lst, count);
// Can't push_front() with a vector:
//! measureTime(InsertFront<VF>(), vec, count);
measureTime(InsertFront<DF>(), deq, count);
measureTime(InsertFront<LF>(), lst, count);
measureTime(InsertMiddle<VF>(), vec, count);
measureTime(InsertMiddle<DF>(), deq, count);
measureTime(InsertMiddle<LF>(), lst, count);
measureTime(RandomAccess<VF>(), vec, count);
measureTime(RandomAccess<DF>(), deq, count);
// Can't operator[] with a list:
//! measureTime(RandomAccess<LF>(), lst, count);
measureTime(Traversal<VF>(), vec, count);
measureTime(Traversal<DF>(), deq, count);
measureTime(Traversal<LF>(), lst, count);
measureTime(Swap<VF>(), vec, count);
measureTime(Swap<DF>(), deq, count);
measureTime(Swap<LF>(), lst, count);
measureTime(RemoveMiddle<VF>(), vec, count);
measureTime(RemoveMiddle<DF>(), deq, count);
measureTime(RemoveMiddle<LF>(), lst, count);
vec.resize(vec.size() * 10); // Make it bigger
measureTime(RemoveBack<VF>(), vec, count);
measureTime(RemoveBack<DF>(), deq, count);
measureTime(RemoveBack<LF>(), lst, count);
} ///:~
Результат под Windows (P4): InsertBack for vector: 0 InsertBack for vector: 0 InsertBack for deque: 0 InsertBack for list: 0 InsertFront for deque: 0 InsertFront for list: 15 InsertMiddle for vector: 0 InsertMiddle for deque: 0 InsertMiddle for list: 0 RandomAccess for vector: 0 RandomAccess for deque: 0 Traversal for vector: 0 Traversal for deque: 0 Traversal for list: 0 Swap for vector: 0 Swap for deque: 0 Swap for list: 0 RemoveMiddle for vector: 15 RemoveMiddle for deque: 0 RemoveMiddle for list: 0 RemoveBack for vector: 0 RemoveBack for deque: 0 RemoveBack for list: 0 |
|
|
Дата: Апр 2, 2004 22:16:11 · Поправил: volodya Пардон, в последнем случае чувствительности счетчика оказалось маловато. Увеличил размер. Имеем: InsertBack for vector: 15 InsertBack for vector: 0 InsertBack for deque: 0 InsertBack for list: 0 InsertFront for deque: 47 InsertFront for list: 47 InsertMiddle for vector: 1094 InsertMiddle for deque: 0 InsertMiddle for list: 0 RandomAccess for vector: 15 RandomAccess for deque: 32 Traversal for vector: 0 Traversal for deque: 15 Traversal for list: 610 Swap for vector: 15 Swap for deque: 0 Swap for list: 16 RemoveMiddle for vector: 1140 RemoveMiddle for deque: 0 RemoveMiddle for list: 0 RemoveBack for vector: 0 RemoveBack for deque: 0 RemoveBack for list: 31 |
|
|
Дата: Апр 5, 2004 16:37:14 ....я почти был в этом уверен, эх, лучше перечитаю Криса Касперски |
|
|
Дата: Апр 5, 2004 18:27:15 У Криса я замечаю тенденцию писать то, в чем он иногда не слишком хорошо разбирается. Хотя все так делают, но он это делает с вышки, как в том анекдоте... |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.045 |