Thanks for the hard data! This is very useful.

The article about atomic reference counting is interesting but mostly compares eager copy with atomic reference counting (I attach one of the result files for convenience). We're also interested in the penalty exacted by atomicity of reference counting when compared with unprotected reference counting. (The trick of returning a smart proxy is clever but C++ specific.) Also, if I understand things correctly, the article does not induce contention; it only measures uncontested operations.

Anyhow, the analysis of the class constructors in Qt is extremely relevant. Thanks again!


Andrei

On 11/3/10 10:00 AM, Max Samukha wrote:
These notes on copy-constructible Qt types may be useful for the discussion:

1. 1/5 (approx. 100 classes) of all classes in core, gui, network,
webkit, svg and opengl packages define public copy-constructors.

A half of those are in reference-counted COW types (approx. 50 classes).
The remaining 50 classes are reference-counted types without COW, types
with allocating copy-constructors and types with trivial non-allocating
constructors.

Most of the types with allocating copy-constructors I would probably
implemented as classes in D. Polymorphic types like QListWidgetItem that
provide the copy-constructor only for clone() reimplementation should
definitely be classes in D.

The conclusion I tend to draw is that expensive copy-constructors can be
avoided in most applications.

2. Reference counters are atomic using interlocked integer operations.
There have been a couple of complaints about performance
[http://www.gotw.ca/publications/optimizations.htm] but those complaints
seem ungrounded
[http://labs.qt.nokia.com/2006/10/16/atomic-reference-counting-is-it-worth-it-2].

3. If a type exposes data by reference, proxy objects are used to avoid
unnecessary copying. For example, QString::operator[](int) returns an
instance of QСharRef, not QChar&. The shared data is copied only if the
QCharRef instance is modified.

On Sun, Oct 31, 2010 at 5:57 AM, Andrei Alexandrescu <[email protected]
<mailto:[email protected]>> wrote:

    I am highly interested in the opinion of Phobos contributors in the
    matter of copy construction (just posted the message below).

    Andrei

    -------- Original Message --------
    Subject: Re: Ruling out arbitrary cost copy construction?
    Date: Sat, 30 Oct 2010 22:56:24 -0500
    From: Andrei Alexandrescu <[email protected]
    <mailto:[email protected]>>
    Newsgroups: digitalmars.D

    On 10/30/2010 09:40 PM, Michel Fortin wrote:

        On 2010-10-30 20:49:38 -0400, Andrei Alexandrescu
        <[email protected]
        <mailto:[email protected]>> said:

            On 10/30/10 2:24 CDT, Don wrote:

                At the moment, I think it's impossible.
                Has anyone succesfully implemented refcounting in D? As
                long as bug 3516
                (Destructor not called on temporaries) remains open, it
                doesn't seem to
                be possible.
                Is that the only blocker, or are there others?


            I managed to define and use RefCounted in Phobos. File also uses
            hand-made reference counting. I think RefCounted is a pretty
            good
            abstraction (unless it hits the bug you mentioned.)


        I like the idea of RefCounted as a way to automatically make things
        reference counted.


    Unfortunately it's only a semi-automated mechanism.

        But like File and many similar ref-counted structs, it has this race
        condition (bug 4624) when stored inside the GC heap. Currently,
        most of
        Phobos's ref-counted structs are race-free only when they reside
        on the
        stack or if your program has only one thread (because the GC doesn't
        spawn threads if I'm correct).

        It's a little sad that the language doesn't prevent races in
        destructors
        (bug 4621).


    I hope we're able to solve these implementation issues that can be seen
    as independent from the decision at hand.

    Walter and I discussed the matter again today and we're on the brink of
    deciding that cheap copy construction is to be assumed. This simplifies
    the language and the library a great deal, and makes it perfectly good
    for 95% of the cases. For a minority of types, code would need to go
    through extra hoops (e.g. COW, refcounting) to be compliant.

    I'm looking for more feedback from the larger D community. This is a
    very important decision that marks one of the largest departures from
    the C++ style. Taking the wrong turn here could alienate many
    programmers coming from C++.

    So, everybody - this is really the time to speak up or forever be
    silent.


    Andrei
    _______________________________________________
    phobos mailing list
    [email protected] <mailto:[email protected]>
    http://lists.puremagic.com/mailman/listinfo/phobos




_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos
Time to run = 1000 ms
--------------------------------------------------

SimpleString copyConstruction:
  length   10, thrA:   6831 per-ms, thrB:   5333 per-ms, thrC:   5338 per-ms
  length  100, thrA:   4244 per-ms, thrB:   4236 per-ms, thrC:   3530 per-ms
  length 1000, thrA:    709 per-ms, thrB:    735 per-ms, thrC:    704 per-ms

SimpleString2 copyConstruction:
  length   10, thrA:   9347 per-ms, thrB:   9393 per-ms, thrC:   9347 per-ms
  length  100, thrA:   3734 per-ms, thrB:   4139 per-ms, thrC:   3302 per-ms
  length 1000, thrA:    727 per-ms, thrB:    670 per-ms, thrC:    696 per-ms

SharedString copyConstruction:
  length   10, thrA: 258302 per-ms
  length  100, thrA: 258064 per-ms
  length 1000, thrA: 257826 per-ms

AtomicString copyConstruction:
  length   10, thrA:  40201 per-ms, thrB:  44077 per-ms, thrC:  40000 per-ms
  length  100, thrA:  35429 per-ms, thrB:  40167 per-ms, thrC:  40033 per-ms
  length 1000, thrA:  40167 per-ms, thrB:  40033 per-ms, thrC:  43915 per-ms

std::string copyConstruction:
  length   10, thrA:  29657 per-ms, thrB:  29657 per-ms, thrC:  29520 per-ms
  length  100, thrA:  29629 per-ms, thrB:  29657 per-ms, thrC:  29520 per-ms
  length 1000, thrA:  29657 per-ms, thrB:  29657 per-ms, thrC:  29520 per-ms

QByteArray copyConstruction:
  length   10, thrA:  40201 per-ms, thrB:  44077 per-ms, thrC:  40000 per-ms
  length  100, thrA:  44117 per-ms, thrB:  40167 per-ms, thrC:  40000 per-ms
  length 1000, thrA:  40167 per-ms, thrB:  40201 per-ms, thrC:  40000 per-ms

--------------------------------------------------

SimpleString appendSingleCharacter:
  length   10, thrA:  17021 per-ms, thrB:  16764 per-ms, thrC:  17123 per-ms
  length  100, thrA:   9991 per-ms, thrB:   9009 per-ms, thrC:   9397 per-ms
  length 1000, thrA:   2498 per-ms, thrB:   2429 per-ms, thrC:   2390 per-ms

SimpleString2 appendSingleCharacter:
  length   10, thrA:  12658 per-ms, thrB:  12298 per-ms, thrC:  12924 per-ms
  length  100, thrA:  36496 per-ms, thrB:  35874 per-ms, thrC:  38610 per-ms
  length 1000, thrA:  77669 per-ms, thrB:  76997 per-ms, thrC:  76923 per-ms

SharedString appendSingleCharacter:
  length   10, thrA:  11320 per-ms
  length  100, thrA:  33472 per-ms
  length 1000, thrA:  64724 per-ms

AtomicString appendSingleCharacter:
  length   10, thrA:  12048 per-ms, thrB:  10000 per-ms, thrC:   9950 per-ms
  length  100, thrA:  32653 per-ms, thrB:  33472 per-ms, thrC:  31872 per-ms
  length 1000, thrA:  61835 per-ms, thrB:  61479 per-ms, thrC:  61420 per-ms

std::string appendSingleCharacter:
  length   10, thrA:  26294 per-ms, thrB:  25974 per-ms, thrC:  26186 per-ms
  length  100, thrA:  63116 per-ms, thrB:  62868 per-ms, thrC:  63429 per-ms
  length 1000, thrA:  90480 per-ms, thrB:  89053 per-ms, thrC:  89887 per-ms

QByteArray appendSingleCharacter:
  length   10, thrA:  21978 per-ms, thrB:  18250 per-ms, thrC:  18168 per-ms
  length  100, thrA:  30217 per-ms, thrB:  28933 per-ms, thrC:  28776 per-ms
  length 1000, thrA:  34572 per-ms, thrB:  34423 per-ms, thrC:  34188 per-ms

--------------------------------------------------

SimpleString nonMutatingAccess:
  length   10, thrA: 225776 per-ms, thrB:  45558 per-ms, thrC:  22779 per-ms
  length  100, thrA: 225988 per-ms, thrB:  38647 per-ms, thrC:  38461 per-ms
  length 1000, thrA: 225776 per-ms, thrB:  23255 per-ms, thrC:  46029 per-ms

SimpleString2 nonMutatingAccess:
  length   10, thrA: 226201 per-ms, thrB:  42283 per-ms, thrC:  42127 per-ms
  length  100, thrA: 226201 per-ms, thrB:  42462 per-ms, thrC:  42283 per-ms
  length 1000, thrA: 225988 per-ms, thrB:  42780 per-ms, thrC:  42553 per-ms

SharedString nonMutatingAccess:
  length   10, thrA: 200913 per-ms
  length  100, thrA: 191754 per-ms
  length 1000, thrA: 200913 per-ms

AtomicString nonMutatingAccess:
  length   10, thrA: 200546 per-ms, thrB:  42949 per-ms, thrC:  42796 per-ms
  length  100, thrA: 200913 per-ms, thrB:  50847 per-ms, thrC:  50632 per-ms
  length 1000, thrA: 201096 per-ms, thrB:  47961 per-ms, thrC:  49668 per-ms

std::string nonMutatingAccess:
  length   10, thrA: 180995 per-ms, thrB:  26058 per-ms, thrC:  25940 per-ms
  length  100, thrA: 180995 per-ms, thrB:  25923 per-ms, thrC:  25806 per-ms
  length 1000, thrA: 180995 per-ms, thrB:  25923 per-ms, thrC:  25806 per-ms

QByteArray nonMutatingAccess:
  length   10, thrA: 178217 per-ms, thrB:  43165 per-ms, thrC:  28985 per-ms
  length  100, thrA: 178217 per-ms, thrB:  29917 per-ms, thrC:  29761 per-ms
  length 1000, thrA: 178748 per-ms, thrB:  30120 per-ms, thrC:  29985 per-ms

--------------------------------------------------

SimpleString nonMutatingAccessAfterCopy:
  length   10, thrA:   9125 per-ms, thrB:   4733 per-ms, thrC:   4710 per-ms
  length  100, thrA:   3816 per-ms, thrB:   2700 per-ms, thrC:   2693 per-ms
  length 1000, thrA:    710 per-ms, thrB:    594 per-ms, thrC:    652 per-ms

SimpleString2 nonMutatingAccessAfterCopy:
  length   10, thrA:   8988 per-ms, thrB:   4619 per-ms, thrC:   4606 per-ms
  length  100, thrA:   3187 per-ms, thrB:   2852 per-ms, thrC:   2786 per-ms
  length 1000, thrA:    703 per-ms, thrB:    649 per-ms, thrC:    613 per-ms

SharedString nonMutatingAccessAfterCopy:
  length   10, thrA: 166975 per-ms
  length  100, thrA: 170777 per-ms
  length 1000, thrA: 170454 per-ms

AtomicString nonMutatingAccessAfterCopy:
  length   10, thrA:  37209 per-ms, thrB:   6149 per-ms, thrC:   6187 per-ms
  length  100, thrA:  37278 per-ms, thrB:   7136 per-ms, thrC:   6802 per-ms
  length 1000, thrA:  37278 per-ms, thrB:   7200 per-ms, thrC:   6855 per-ms

std::string nonMutatingAccessAfterCopy:
  length   10, thrA:   7312 per-ms, thrB:   3623 per-ms, thrC:   3590 per-ms
  length  100, thrA:   4869 per-ms, thrB:   3007 per-ms, thrC:   2996 per-ms
  length 1000, thrA:   3266 per-ms, thrB:   2146 per-ms, thrC:   2502 per-ms

QByteArray nonMutatingAccessAfterCopy:
  length   10, thrA:  38498 per-ms, thrB:   6097 per-ms, thrC:   6065 per-ms
  length  100, thrA:  38498 per-ms, thrB:   6046 per-ms, thrC:   6019 per-ms
  length 1000, thrA:  38461 per-ms, thrB:   6092 per-ms, thrC:   6060 per-ms

--------------------------------------------------

SimpleString nonMutatingAccessOnCopy:
  length   10, thrA:   9384 per-ms, thrB:   4780 per-ms, thrC:   4757 per-ms
  length  100, thrA:   4214 per-ms, thrB:   2714 per-ms, thrC:   2718 per-ms
  length 1000, thrA:    711 per-ms, thrB:    674 per-ms, thrC:    648 per-ms

SimpleString2 nonMutatingAccessOnCopy:
  length   10, thrA:   9448 per-ms, thrB:   4615 per-ms, thrC:   4351 per-ms
  length  100, thrA:   3220 per-ms, thrB:   2906 per-ms, thrC:   2173 per-ms
  length 1000, thrA:    703 per-ms, thrB:    648 per-ms, thrC:    607 per-ms

SharedString nonMutatingAccessOnCopy:
  length   10, thrA: 168855 per-ms
  length  100, thrA: 170940 per-ms
  length 1000, thrA: 170940 per-ms

AtomicString nonMutatingAccessOnCopy:
  length   10, thrA:  40145 per-ms, thrB:   6672 per-ms, thrC:   6639 per-ms
  length  100, thrA:  40182 per-ms, thrB:   6130 per-ms, thrC:   6102 per-ms
  length 1000, thrA:  40182 per-ms, thrB:   6069 per-ms, thrC:   6042 per-ms

std::string nonMutatingAccessOnCopy:
  length   10, thrA:   5925 per-ms, thrB:   3487 per-ms, thrC:   3472 per-ms
  length  100, thrA:   4064 per-ms, thrB:   2968 per-ms, thrC:   2653 per-ms
  length 1000, thrA:   3324 per-ms, thrB:   2380 per-ms, thrC:   2371 per-ms

QByteArray nonMutatingAccessOnCopy:
  length   10, thrA:  38461 per-ms, thrB:   6106 per-ms, thrC:   6079 per-ms
  length  100, thrA:  38461 per-ms, thrB:   6074 per-ms, thrC:   6046 per-ms
  length 1000, thrA:  38461 per-ms, thrB:   6083 per-ms, thrC:   6056 per-ms

--------------------------------------------------

SimpleString mutatingCopy1:
  length   10, thrA:   6666 per-ms, thrB:   5161 per-ms, thrC:   5022 per-ms
  length  100, thrA:   2819 per-ms, thrB:   2488 per-ms, thrC:   2533 per-ms
  length 1000, thrA:    525 per-ms, thrB:    511 per-ms, thrC:    500 per-ms

SimpleString2 mutatingCopy1:
  length   10, thrA:   8349 per-ms, thrB:   6361 per-ms, thrC:   6349 per-ms
  length  100, thrA:   3567 per-ms, thrB:   3254 per-ms, thrC:   2772 per-ms
  length 1000, thrA:    699 per-ms, thrB:    674 per-ms, thrC:    644 per-ms

SharedString mutatingCopy1:
  length   10, thrA:   5484 per-ms
  length  100, thrA:   4109 per-ms
  length 1000, thrA:   1634 per-ms

AtomicString mutatingCopy1:
  length   10, thrA:   5104 per-ms, thrB:   4236 per-ms, thrC:   4184 per-ms
  length  100, thrA:   3745 per-ms, thrB:   3448 per-ms, thrC:   3348 per-ms
  length 1000, thrA:   1614 per-ms, thrB:   1413 per-ms, thrC:   1474 per-ms

std::string mutatingCopy1:
  length   10, thrA:   7561 per-ms, thrB:   5812 per-ms, thrC:   5823 per-ms
  length  100, thrA:   5431 per-ms, thrB:   4236 per-ms, thrC:   4444 per-ms
  length 1000, thrA:   4532 per-ms, thrB:   3463 per-ms, thrC:   3773 per-ms

QByteArray mutatingCopy1:
  length   10, thrA:   9621 per-ms, thrB:   6672 per-ms, thrC:   6705 per-ms
  length  100, thrA:   6883 per-ms, thrB:   5095 per-ms, thrC:   4771 per-ms
  length 1000, thrA:   3103 per-ms, thrB:   2554 per-ms, thrC:   2543 per-ms

--------------------------------------------------

SimpleString mutatingCopy2:
  length   10, thrA:   5109 per-ms, thrB:   4387 per-ms, thrC:   4355 per-ms
  length  100, thrA:   2105 per-ms, thrB:   1836 per-ms, thrC:   1974 per-ms
  length 1000, thrA:    398 per-ms, thrB:    357 per-ms, thrC:    386 per-ms

SimpleString2 mutatingCopy2:
  length   10, thrA:   8101 per-ms, thrB:   6482 per-ms, thrC:   6514 per-ms
  length  100, thrA:   3543 per-ms, thrB:   3193 per-ms, thrC:   3184 per-ms
  length 1000, thrA:    718 per-ms, thrB:    708 per-ms, thrC:    699 per-ms

SharedString mutatingCopy2:
  length   10, thrA:   6786 per-ms
  length  100, thrA:   5343 per-ms
  length 1000, thrA:   2140 per-ms

AtomicString mutatingCopy2:
  length   10, thrA:   6225 per-ms, thrB:   4835 per-ms, thrC:   4815 per-ms
  length  100, thrA:   4806 per-ms, thrB:   3773 per-ms, thrC:   3755 per-ms
  length 1000, thrA:   2060 per-ms, thrB:   1838 per-ms, thrC:   1906 per-ms

std::string mutatingCopy2:
  length   10, thrA:   6844 per-ms, thrB:   5683 per-ms, thrC:   5658 per-ms
  length  100, thrA:   4240 per-ms, thrB:   4440 per-ms, thrC:   3571 per-ms
  length 1000, thrA:   3917 per-ms, thrB:   3254 per-ms, thrC:   3246 per-ms

QByteArray mutatingCopy2:
  length   10, thrA:   8963 per-ms, thrB:   6717 per-ms, thrC:   6639 per-ms
  length  100, thrA:   6617 per-ms, thrB:   5755 per-ms, thrC:   5363 per-ms
  length 1000, thrA:   3669 per-ms, thrB:   3053 per-ms, thrC:   3059 per-ms

--------------------------------------------------

SimpleString functionWithArgument:
  length   10, thrA:   8783 per-ms, thrB:   8648 per-ms, thrC:   8435 per-ms
  length  100, thrA:   4116 per-ms, thrB:   3966 per-ms, thrC:   3824 per-ms
  length 1000, thrA:    708 per-ms, thrB:    717 per-ms, thrC:    705 per-ms

SimpleString2 functionWithArgument:
  length   10, thrA:   9338 per-ms, thrB:   9421 per-ms, thrC:   9266 per-ms
  length  100, thrA:   3237 per-ms, thrB:   4166 per-ms, thrC:   3748 per-ms
  length 1000, thrA:    703 per-ms, thrB:    703 per-ms, thrC:    722 per-ms

SharedString functionWithArgument:
  length   10, thrA: 120481 per-ms
  length  100, thrA: 120481 per-ms
  length 1000, thrA: 120481 per-ms

AtomicString functionWithArgument:
  length   10, thrA:  37735 per-ms, thrB:  38131 per-ms, thrC:  34058 per-ms
  length  100, thrA:  38314 per-ms, thrB:  38314 per-ms, thrC:  34253 per-ms
  length 1000, thrA:  38277 per-ms, thrB:  28419 per-ms, thrC:  33613 per-ms

std::string functionWithArgument:
  length   10, thrA:  28045 per-ms, thrB:  22263 per-ms, thrC:  27916 per-ms
  length  100, thrA:  28045 per-ms, thrB:  22160 per-ms, thrC:  27916 per-ms
  length 1000, thrA:  28045 per-ms, thrB:  22325 per-ms, thrC:  24496 per-ms

QByteArray functionWithArgument:
  length   10, thrA:  37523 per-ms, thrB:  37002 per-ms, thrC:  38167 per-ms
  length  100, thrA:  37488 per-ms, thrB:  38314 per-ms, thrC:  38204 per-ms
  length 1000, thrA:  38277 per-ms, thrB:  37629 per-ms, thrC:  38204 per-ms

--------------------------------------------------

SimpleString functionWithTemporaryArgument:
  length   10, thrA:   9320 per-ms, thrB:   9329 per-ms, thrC:   9213 per-ms
  length  100, thrA:   4170 per-ms, thrB:   3597 per-ms, thrC:   4148 per-ms
  length 1000, thrA:    707 per-ms, thrB:    709 per-ms, thrC:    727 per-ms

SimpleString2 functionWithTemporaryArgument:
  length   10, thrA:   9142 per-ms, thrB:   9266 per-ms, thrC:   9204 per-ms
  length  100, thrA:   3700 per-ms, thrB:   3610 per-ms, thrC:   3275 per-ms
  length 1000, thrA:    699 per-ms, thrB:    701 per-ms, thrC:    722 per-ms

SharedString functionWithTemporaryArgument:
  length   10, thrA: 120585 per-ms
  length  100, thrA: 120481 per-ms
  length 1000, thrA: 120481 per-ms

AtomicString functionWithTemporaryArgument:
  length   10, thrA:  37771 per-ms, thrB:  38167 per-ms, thrC:  34383 per-ms
  length  100, thrA:  38350 per-ms, thrB:  38387 per-ms, thrC:  33426 per-ms
  length 1000, thrA:  38350 per-ms, thrB:  38424 per-ms, thrC:  32936 per-ms

std::string functionWithTemporaryArgument:
  length   10, thrA:  28045 per-ms, thrB:  22058 per-ms, thrC:  24013 per-ms
  length  100, thrA:  28045 per-ms, thrB:  22201 per-ms, thrC:  23121 per-ms
  length 1000, thrA:  23483 per-ms, thrB:  22325 per-ms, thrC:  24158 per-ms

QByteArray functionWithTemporaryArgument:
  length   10, thrA:  37488 per-ms, thrB:  37418 per-ms, thrC:  37278 per-ms
  length  100, thrA:  38277 per-ms, thrB:  37140 per-ms, thrC:  38167 per-ms
  length 1000, thrA:  38387 per-ms, thrB:  37488 per-ms, thrC:  38131 per-ms

--------------------------------------------------

SimpleString functionReturningCopy:
  length   10, thrA:   9257 per-ms, thrB:   9275 per-ms, thrC:   9266 per-ms
  length  100, thrA:   4206 per-ms, thrB:   4057 per-ms, thrC:   3327 per-ms
  length 1000, thrA:    709 per-ms, thrB:    619 per-ms, thrC:    598 per-ms

SimpleString2 functionReturningCopy:
  length   10, thrA:   9014 per-ms, thrB:   7239 per-ms, thrC:   9160 per-ms
  length  100, thrA:   3152 per-ms, thrB:   2369 per-ms, thrC:   2791 per-ms
  length 1000, thrA:    725 per-ms, thrB:    689 per-ms, thrC:    722 per-ms

SharedString functionReturningCopy:
  length   10, thrA: 112676 per-ms
  length  100, thrA: 112576 per-ms
  length 1000, thrA: 112464 per-ms

AtomicString functionReturningCopy:
  length   10, thrA:  37664 per-ms, thrB:  38910 per-ms, thrC:  38461 per-ms
  length  100, thrA:  37664 per-ms, thrB:  38910 per-ms, thrC:  37523 per-ms
  length 1000, thrA:  37664 per-ms, thrB:  37700 per-ms, thrC:  38572 per-ms

std::string functionReturningCopy:
  length   10, thrA:  27000 per-ms, thrB:  27397 per-ms, thrC:  27290 per-ms
  length  100, thrA:  27424 per-ms, thrB:  27000 per-ms, thrC:  26871 per-ms
  length 1000, thrA:  27000 per-ms, thrB:  27000 per-ms, thrC:  27290 per-ms

QByteArray functionReturningCopy:
  length   10, thrA:  38872 per-ms, thrB:  38910 per-ms, thrC:  37523 per-ms
  length  100, thrA:  38910 per-ms, thrB:  37700 per-ms, thrC:  38759 per-ms
  length 1000, thrA:  38948 per-ms, thrB:  37664 per-ms, thrC:  38535 per-ms

--------------------------------------------------

_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to