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

  • 相关阅读:
    ntp时间服务器
    locate 命令
    身份验证器
    centos 6 mysql源码安装
    简单上传下载命令lrzsz
    iptables记录日志
    iptables日志探秘
    du 命令
    Codeforces 1097F Alex and a TV Show (莫比乌斯反演)
    线段树教做人系列(1)HDU4967 Handling the Past
  • 原文地址:https://www.cnblogs.com/kex1n/p/1646849.html
Copyright © 2011-2022 走看看