我使用std::map<std::pair<int, int>, class B>
来保存网格图的信息,B类包含大约10000字节的数据。我发现40000次find
操作需要大约10ms,尽管地图只有四个键值。当我将B类数据大小减少到2500字节时,成本也降低到大约3.5ms。我知道查找操作的时间复杂度是O(log(N)),这是什么原因造成的?
答案 0 :(得分:0)
我很好奇并尝试了一个简单的测试。测试代码如下(使用VS2015编译)。
这是我在发布版本中运行代码时所获得的(优化):
Value10k: 0.126498 ms Value2k: 0.121991 ms
这是调试版本中的输出:
Value10k: 120.187 ms Value2k: 95.5364 ms
在发布版本中,差异可以忽略不计;在调试版本中,似乎存在一些差异(尽管对于性能数据,我倾向于更喜欢发布版本。)
我不知道map::find
方法的实现细节。无论如何,请注意,大O符号只是故事的一部分。要考虑性能的另一个重要方面是数据的缓存友好性,数据位置等。
我甚至不知道你的B级是否有一些昂贵的复制操作正在进行中。
无论如何,我建议衡量您的代码效果,并与其他变体进行比较,例如使用unique_ptr<B>
或shared_ptr<B>
作为地图的价值。
可编译的测试代码如下:
#include <iostream>
#include <map>
#include <windows.h>
using namespace std;
template <int DimT>
struct Value
{
char Data[DimT];
};
typedef Value<10000> Value10k;
typedef Value<2000> Value2k;
long long Counter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return li.QuadPart;
}
long long Frequency()
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
return li.QuadPart;
}
void PrintTime(const long long start, const long long finish, const char * const msg)
{
cout << msg << ": " << (finish - start) * 1000.0 / Frequency() << " ms\n";
}
bool IsEven(int n)
{
return (n % 2) == 0;
}
int main()
{
map<pair<int, int>, Value10k> m1;
m1[make_pair(0, 0)] = Value10k{};
m1[make_pair(0, 1)] = Value10k{};
m1[make_pair(1, 0)] = Value10k{};
m1[make_pair(1, 1)] = Value10k{};
constexpr int searchCount = 40000;
auto start = Counter();
for (int i = 0; i < searchCount; i++)
{
int x{};
int y{};
if (IsEven(i))
{
x = 0;
y = 1;
}
else
{
x = 1;
y = 0;
}
auto search = m1.find(make_pair(x, y));
}
auto finish = Counter();
PrintTime(start, finish, "Value10k");
map<pair<int, int>, Value2k> m2;
m2[make_pair(0, 0)] = Value2k{};
m2[make_pair(0, 1)] = Value2k{};
m2[make_pair(1, 0)] = Value2k{};
m2[make_pair(1, 1)] = Value2k{};
start = Counter();
for (int i = 0; i < searchCount; i++)
{
int x{};
int y{};
if (IsEven(i))
{
x = 0;
y = 1;
}
else
{
x = 1;
y = 0;
}
auto search = m2.find(make_pair(x, y));
}
finish = Counter();
PrintTime(start, finish, "Value2k");
}