Hi all,

I ran the attached test case, s.cpp, and timed it:

* Deep copy

$ for f in 16 8 6 4 2 1; do time ./s $f 100000000; done

16      0m39.292s       2m34.381s       0m0.035s
8       0m20.573s       1m18.131s       0m0.025s
6       0m15.037s       0m58.269s       0m0.009s
4       0m9.973s        0m38.657s       0m0.009s
2       0m8.750s        0m17.473s       0m0.016s
1       0m8.499s        0m8.495s        0m0.002s

* Shallow copy

$ for f in 16 8 6 4 2 1; do time ./s $f 100000000; done

16      5m29.311s       4m2.107s        17m39.634s
8       2m43.635s       2m1.823s        8m50.454s
6       2m10.601s       2m2.316s        6m18.462s
4       1m20.766s       1m35.383s       3m29.467s
2       0m25.146s       0m27.775s       0m22.408s
1       0m3.557s        0m3.555s        0m0.000s

The results show a counter-intuitive better performance for deep-copied strings. Again, there is the reversal of performance for one-threaded programs where there is no contention.

Liviu
#include <iostream>
#include <locale>

#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <pthread.h>
#include <unistd.h>

#define MAX_THREADS 128

static long nloops = 10000000, nthreads = 16;
static bool volatile pwait = true;

////////////////////////////////////////////////////////////////////////

extern "C" {

static void* 
f (void* pv)
{
    std::string const& s = *reinterpret_cast< std::string* > (pv);

    volatile unsigned long n = 0;

    while (pwait) ;

    for (int i = 0; i < nloops; ++i) {
#if !defined (NO_DEEP_COPY)
        const std::string tmp (s.c_str ());
#else
        const std::string tmp = s;
#endif // NO_DEEP_COPY

        n += strlen (tmp.c_str ());
    }

    return (void*)n;
}

} // extern "C"

int
main (int argc, char** argv)
{
    switch (argc) {
    case 3:
        nloops = atol (argv [2]);
    case 2:
        nthreads = atol (argv [1]);
        break;
    }

    pthread_t tid [MAX_THREADS] = { 0 };

    if (nthreads > MAX_THREADS)
        nthreads = MAX_THREADS;

    printf ("%ld, %ld\n", nthreads, nloops);

    pthread_setconcurrency (nthreads);

    std::string s ("Hello, world.");
    
    for (int i = 0; i < nthreads; ++i) {
        if (pthread_create (tid + i, 0, f, &s))
            exit (-1);
    }

    usleep (50);
    pwait = false;

    for (int i = 0; i < nthreads; ++i) {
        if (tid [i])
            pthread_join (tid [i], 0);
    }

    return 0;
}


* Deep-copy

$ for f in 16 8 6 4 2 1; do time ./s $f 100000000; done

16      0m39.292s       2m34.381s       0m0.035s
8       0m20.573s       1m18.131s       0m0.025s
6       0m15.037s       0m58.269s       0m0.009s
4       0m9.973s        0m38.657s       0m0.009s
2       0m8.750s        0m17.473s       0m0.016s
1       0m8.499s        0m8.495s        0m0.002s

* Ref-counted

16      5m29.311s       4m2.107s        17m39.634s
8       2m43.635s       2m1.823s        8m50.454s
6       2m10.601s       2m2.316s        6m18.462s
4       1m20.766s       1m35.383s       3m29.467s
2       0m25.146s       0m27.775s       0m22.408s
1       0m3.557s        0m3.555s        0m0.000s

Reply via email to