zoukankan      html  css  js  c++  java
  • 慎用Visual Studio C++默认的hash_map转载

    写了一个模块客户端和服务器共用,为了加快查询速度,用了hash_map,今天一个兄弟老卢测试说将其中的hash_map替换成map后速度更快,有点晕。自己写了一段代码在Windows下用Visual Studio C++测试hashmap。

    首先说明,hashmap目前还没有进入C++的规范,但是大部分厂商都实现了这个容器,测试的hashmap有两种:

    l          Visual Studio 2003自己默认带的hash_map,

    l          STLport的hash_map

    当然用过Visual Studio默认自带的hashmap的兄弟会知道,其和SGI的一脉的STL实现不太一样,包括模板声明方式等都自成一套。所以其实使用的时候还要注意。这儿就不啰嗦这个问题了。同时麻烦大家注意我测试的版本是2003,使用的是DEBUG版本。

    测试代码如下,如果你觉得枯燥,可以跳过这段看代码直接看结果,代码其中用了ACE的一些代码测试时间差:

    #include <stdio.h>

    #include <iostream>

    #include <map>

    #include <hash_map>

    #include <ace/OS.h>

    #include <ace/Time_Value.h>

     

     

    void test_hash_map()

     

    {

     

        ACE_Time_Value tvStart(0);

        ACE_Time_Value tvEnd(0);

        ACE_Time_Value tvPassTime(0);

        tvStart = ACE_OS::gettimeofday();

     

        hash_map<size_t,int>   int_hash_map;

        //测试10万次

    const size_t TEST_NUMBER = 10*10000;

    //注意这行代码,VS.NET默认的STL没有这个函数的,而STLPort的实现有这个函数

        int_hash_map.resize(TEST_NUMBER);

     

        //顺序插入一组数据

        for (size_t i= 0;i<TEST_NUMBER;++i)

        {

            int_hash_map[i]=0;

        }

     

        //查询20万次,一般能查询到,一半不能查询到

        for (size_t i= 0;i<2*TEST_NUMBER;++i)

        {

            int_hash_map.find(i);

        }

        //得到毫秒的时间差

        tvEnd = ACE_OS::gettimeofday();

        tvPassTime = tvEnd - tvStart;

        cout<<"test_hash_map gettimeofday :"<<tvPassTime.msec()<<" "<<endl;

      

    };

     

    void test_map()

     

    {

     

        ACE_Time_Value tvStart(0);

        ACE_Time_Value tvEnd(0);

        ACE_Time_Value tvPassTime(0);

        tvStart = ACE_OS::gettimeofday();

     

    map<size_t,int>   int_map;

    //测试10万个数据

        const size_t TEST_NUMBER = 10*10000;

       

        for (size_t i= 0;i<TEST_NUMBER;++i)

        {

            int_map[i]=0;

        }

     

        for (size_t i= 0;i<2*TEST_NUMBER;++i)

     

        {

            int_map.find(i);

    }

    //得到毫秒的时间差

        tvEnd = ACE_OS::gettimeofday();

        tvPassTime = tvEnd - tvStart;

        cout<<"test_map gettimeofday :"<<tvPassTime.msec()<<" "<<endl;

     

    };

     

    int main(int argc, char* argv[])

     

    {

        for (int j=0;j<10;++j)

        {

            test_hash_map();

            test_map();

        }

        return 0;

    }

    使用Visual Studio 默认的STL的测试结果是,比较让人惊讶的是hash_map的速度不比map快多少,(在我一个同事的VS2005的机器上测试,map居然比hash_map快),节约篇幅,只写了2组测试结果。其他测试结果偏差不大。

    test_hash_map gettimeofday :3093

    test_map gettimeofday :3484

    test_hash_map gettimeofday :3250

    test_map gettimeofday :3531

    而使用STLPort的测试结果如下:hash_map速度比MS的实现快了一倍多,map也比MS的实现快。

    test_hash_map gettimeofday :1312

    test_map gettimeofday :2359

    test_hash_map gettimeofday :1312

    test_map gettimeofday :2375

    而由于MS的hash_map实现没有resize函数,我单独对STLport的实现测试了先使用resize函数的结果如下,大家可以发现如果先使用resize函数,速度可以得到更大的提高。

    test_hash_map gettimeofday :1015

    test_map gettimeofday :2343

    test_hash_map gettimeofday :1031

    test_map gettimeofday :2375

     

    我对STLport的hash_map的实现比较熟悉,应该就是hash因子的数组加List存放数据。而MS Visual Studio的实现我初步浏览了一下,应该也类似,具体原因就说不清了,我也不太想耗费体能找出问题的症结所在,就只看表面现象吧。

    所以大家在使用Visual Studio 的hash_map的时候要当心了,

    l          第一,这个hash_map实现不怎么快,

    l          第二,微软的实现不地道,,基本可以肯定SGI的实现会是默认的标准,有兴趣可以看看BOOST的unordered_map,未来的hash_map应该就是这个样子。

    l          第三,没有resize函数,这样几乎可以肯定,这个实现的大容量时的表现应该很烂。我的同事测试在2005下测试上面的程序,测试数量改为了100万后,他的说法是他最后没有耐心等待结果了。而我用2003的STLport测试结果是10s多完成测试。为什么我敢肯定,建议大家去看看hash_map的实现。

    另外inmore看了我的测试结果说好像MS实现的迭代器遍历要快,我测试了一下,发现果真如此,难道微软的工程师昏了头,优化hash_map的迭代器遍历去了,但多少怀疑这和MS实现还是有一定得关系。

    Microsoft的自己的编译器,实现的东西居然比别人慢一个数量级,MS的工程师应该羞愧一个。测试限于2003和2005,没有涉及2008,但我基本也不抱太大希望。当然,我在这儿也不劝你把所有的东西替换为STLport的实现,为啥呢?如果你用的第三方库很多,这个成本过高了。除非你和我一样,是一个在Windows下调试服务器代码的异类。

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fullsail/archive/2009/06/01/4230312.aspx

  • 相关阅读:
    mysql报错:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone.
    MD5登陆密码的生成
    15. 3Sum、16. 3Sum Closest和18. 4Sum
    11. Container With Most Water
    8. String to Integer (atoi)
    6. ZigZag Conversion
    5. Longest Palindromic Substring
    几种非线性激活函数介绍
    AI初探1
    AI初探
  • 原文地址:https://www.cnblogs.com/kex1n/p/1646849.html
Copyright © 2011-2022 走看看