C++ 地图查找性能与 PHP 数组查找性能

Posted

技术标签:

【中文标题】C++ 地图查找性能与 PHP 数组查找性能【英文标题】:C++ map lookup performance vs PHP array lookup performance 【发布时间】:2011-12-25 05:46:41 【问题描述】:

我无法理解以下内容,我希望有人能为我解释一下:

在 C++ 中,如果我创建一个包含 2M 不同文本位(testdata)的测试数据向量,然后使用这些字符串作为索引值创建一个映射,然后查找所有值,如下所示:

 //Create test data
for(int f=0; f<loopvalue; f++)
   
    stringstream convertToString;
    convertToString << f;
    string strf = convertToString.str();
    testdata[f] = "test" + strf;


    time_t startTimeSeconds = time(NULL);

   for(int f=0; f<2000000; f++) testmap[ testdata[f] ] = f; //Write to map
   for(int f=0; f<2000000; f++) result = testmap[ testdata[f] ]; //Lookup

   time_t endTimeSeconds = time(NULL);
   cout << "Time taken " << endTimeSeconds - startTimeSeconds << "seconds." << endl;

需要 10 秒。

如果我在 php 中看起来至少是一样的:

<?php
$starttime = time();
$loopvalue = 2000000;

//fill array
for($f=0; $f<$loopvalue; $f++)

    $filler = "test" . $f;
    $testarray[$filler] = $f;


//look up array
for($f=0; $f<$loopvalue; $f++)

    $filler = "test" . $f;
    $result = $testarray[$filler];


$endtime = time();
echo "Time taken ".($endtime-$starttime)." seconds.";
?>

...只需 3 秒。

鉴于 PHP 是用 C 编写的,有谁知道 PHP 如何实现这种更快的文本索引查找?

谢谢 C

【问题讨论】:

将字符串键映射切换到std::unordered_map&lt;std::string, int&gt; 并惊讶于差异。你可以对另一张地图做同样的事情,想想看。如果您没有该课程,请考虑 std::tr1::unordered_map&lt;tr1/unordered_map&gt; 您对 C++ 代码使用了哪些编译器设置?尤其是哪个编译器和什么级别的优化? result = testmap[ testdata[f] ] = f 是错字吗? 抱歉错字...已更正。 我只围绕查找移动了时间并使用了 unordered_map,果然它要快得多,PHP 和 C++ 之间的速度相同。我期待 C++ 更快。我正在使用 g++,我现在正在研究编译器优化。 【参考方案1】:

您的循环不是绝对等价的算法。 请注意,在您拥有的 C++ 版本中

    testmap[ testdata[f] ] - 这实际上是查找 + 插入 testmap[ testdata[f] ] - 2 次查找

在 PHP 版本中,您只需在第一个循环中插入并在第二个循环中查找。

PHP 被解释 - 通常如果你的代码在 PHP 中更快,请先检查代码! ;-)

【讨论】:

【参考方案2】:

根据another question,PHP中的关联数组实现为hash tables,平均搜索复杂度为O(1),而C++中的std::map是搜索复杂度为O(log n ),速度较慢。

【讨论】:

可以说,这里重要的不是哈希表和二叉搜索树之间的理论复杂度差异,而是字符串比较非常慢的事实。散列使​​ that 方面更加高效。如果您尝试对以整数为键的映射进行相同操作,我怀疑差异会很大。 @Kerrek SB 你是对的,但是你可以通过把数字放在前面来节省一些字符串比较的时间。【参考方案3】:

我怀疑你的基准测试是错误的。 无论如何,我使用了您的代码(必须对您的数据类型做出一些假设),以下是我机器上的结果:

PHP: 耗时 2 秒。

C++(使用 std::map): 耗时 3 秒。

C++(使用 std::tr1::unordered_map): 耗时 1 秒。

编译的 C++
g++ -03

这是我的测试 C++ 代码:

#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <iostream>
#include <tr1/unordered_map>


int main()
    const int loopvalue=2000000;
    std::vector<std::string> testdata(loopvalue);
    std::tr1::unordered_map<std::string, int> testmap;
    std::string result;
    for(int f=0; f<loopvalue; f++)
       
        std::stringstream convertToString;
        convertToString << f;
        std::string strf = convertToString.str();
        testdata[f] = "test" + strf;
    

    time_t startTimeSeconds = time(NULL);

    for(int f=0; f<loopvalue; f++) testmap[ testdata[f] ] = f; //Write to map
    for(int f=0; f<loopvalue; f++) result = testmap[ testdata[f] ]; //Lookup

    time_t endTimeSeconds = time(NULL);
    std::cout << "Time taken " << endTimeSeconds - startTimeSeconds << "seconds." << std::endl;

结论:

您测试了未优化的 C++ 代码,甚至可能使用 VC++ 编译,在调试模式下编译时,默认情况下会在 std::vector::operator[] 中进行边界检查。

当我们使用 std::map 时,PHP 与优化的 C++ 代码仍然存在差异,因为查找复杂度不同(请参阅 n0rd 的答案),但使用 Hashmap 时 C++ 更快。

【讨论】:

当然,对于基准测试,除其他外,应该使用粒度更细的计时函数。

以上是关于C++ 地图查找性能与 PHP 数组查找性能的主要内容,如果未能解决你的问题,请参考以下文章

for循环遍历查找数据与sqlite数据库查找数据性能问题

二分查找会更快吗?Python中的二分查找与线性查找性能测试

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(ubuntu g++)——遍历和查找

使用XHProf查找PHP性能瓶颈

如何在堆栈上分配数组以获得性能提升?

C++拾趣——STL容器的插入删除遍历和查找操作性能对比(Windows VirtualStudio)——遍历和删除