简体   繁体   中英

why in this code the sort in C++ is much slower than qsort in C (for string array)?

In the book The C++ Programming Language (4th Edition) , Stroustrup say that sort is much faster than qsort , but in my experiment, I got a different result, could any one help me to explain Why?

Here is my code :

double begin_time=0, end_time=0, elapsed_time=0;

vector<string> vs1 = { "fsfaa", "errer", "weesa", "yuyre", "wedsa", "xcxcx" };
begin_time = clock();

for (int i = 0; i < 1000000; i++)
{
    std::sort(vs1.begin(), vs1.end());
}

end_time = clock();
elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;

printf("\n\nElapsed time: %f\n", elapsed_time);

const char* vs[] = { "fsfaa", "errer", "weesa", "yuyre", "wedsa", "xcxcx" };
begin_time = clock();

for (int i = 0; i < 1000000; i++)
{
    std::qsort(vs, sizeof(vs) / sizeof(*vs), sizeof(*vs), (int(*)(const void*, const void*))compare_function);
}

end_time = clock();
elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;
printf("\n\nElapsed time: %f\n", elapsed_time);

and,

int compare_function(const void * a, const void * b) {
const char *pa = *(const char**)a;
const char *pb = *(const char**)b;

return strcmp(pa, pb);

}

Here is the result(Windows/Visual Studio):

Elapsed time: 0.245000
Elapsed time: 0.090000

Update: Thanks for advice, I had changed the code as follow:

int compFunc_2(const void * a, const void * b) {
    const char *pa = *(char**)a;
    const char *pb = *(char**)b;

    return strcmp(pa, pb);
}

bool compFunc(const char *c1, const char *c2)
{
    return strcmp(c1, c2) < 0;
}

string gen_random_str(int len)
{
    string str;
    string w = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    for (int i = 0; i < len; i++)
    {
        str += w[rand() % sizeof(w)];
    }
    return str;
}

char *convert(const std::string & s)
{
    char *pc = new char[s.size() + 1];
    strcpy(pc, s.c_str());
    return pc;
}


int main()
{

    srand((unsigned)time(0));
    const int str_num = 1000000;
    vector<string> vs;
    vector<char*>  vc;
    vector<char*>  vc2; //
    char**  as = new char*[str_num];

    for (int i = 0; i < str_num; i++)
    {
        string tmp = gen_random_str(10);  // length is 10
        vs.push_back(tmp);
        as[i] = new char(tmp.size() + 1);
        strcpy(as[i], tmp.c_str());
    }
    transform(vs.begin(), vs.end(), std::back_inserter(vc), convert);
    transform(vs.begin(), vs.end(), std::back_inserter(vc2), convert);



    double begin_time = 0, end_time, elapsed_time;

    begin_time = clock();
    std::qsort(&vc[0], str_num, sizeof(vc[0]), (int(*)(const void*, const void*))compFunc_2);
    end_time = clock();
    elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;
    printf("\n[1] vector<char*>(qsort) Elapsed time: %f", elapsed_time);

    begin_time = clock();
    std::sort(vc2.begin(), vc2.end(), compFunc);
    end_time = clock();
    elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;
    printf("\n[2] vector<char*>(sort) Elapsed time: %f", elapsed_time);



    printf("\nOther test:");
    begin_time = clock();
    std::qsort(as, str_num, sizeof(as[0]), (int(*)(const void*, const void*))compFunc_2);
    end_time = clock();
    elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;
    printf("\n[3] char array(qsort)   Elapsed time: %f", elapsed_time); 

    begin_time = clock();
    std::sort(vs.begin(), vs.end());
    end_time = clock();
    elapsed_time = double(end_time - begin_time) / CLOCKS_PER_SEC;
    printf("\n[4] vector<string>(sort) Elapsed time: %f", elapsed_time);

    // clean
    cin.get();
    return 0;
}

And, I got the result on my computer:

[1] vector<char*>(qsort) Elapsed time: 1.752000
[2] vector<char*>(sort) Elapsed time: 6.004000
Other test:
[3] char array(qsort)   Elapsed time: 1.691000
[4] vector<string>(sort) Elapsed time: 46.663000

as some say, yes, there is no comparison between [1] and [3]/[4](because of the different data), but I'm still confused about [1] and [2], why the sort seems still slower? (I had closed the Optimize in VS), any help would be great appreciate .

There are many problems in your benchmark that prevent you from making any conclusions form it:

  1. You compare std::sort ing a std::vector of std::strings with qsort ing an array of char* s. Proper benchmark should use the same data structures.

  2. An set size of 6 is not representative for benchmark by a few orders of magnitude.

  3. Both algorithms sort in place, so despite performing one million iterations each, only first actually performs sort. The following 999999 iteration "sort" already sorted data.

  4. You don't do anything meaningful with sorted data, so compiler might even remove your code.

The problem was found,as @manni66 pointed out, I made a big mistake.. I used Debug mode , when I changed to Release mode, the result was reasonable:

[1] vector<char*>(qsort) Elapsed time: 0.559000
[2] vector<char*>(sort) Elapsed time: 0.530000
Other test:
[3] char array(qsort)   Elapsed time: 0.512000
[3] vector<string>(sort) Elapsed time: 0.620000

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM