Is Implicit Sharing always a good thing?



  • My first reaction to it is that it proliferates the places in your code where you have to deal with errors such as Out of Memory. And that this completely out weighs any benefits that you get from using them. If you know you are going change the new object then you copy it once at the start and you then only have one possible failure location in your code (you also get a very marginal performance gain as you don't have all the reference counting going on). I've done several searches for 'Implicit Sharing' and I've found no mention of this issue anywhere - am I therefore missing something obvious?



  • Out of memory errors are not so very likely. What's more: handling them is neigh on impossible in many cases. That's why they are not seen as very important, AFAIK. The common case really is that implicit sharing is usually the faster, and thus the better solution. But you are right, it is not always the best solution.

    If you want, you can always explicitly (force a) detach (of) your shallow copy, and force a deep copy at the place you want it.



  • Implictitly sharing is (IMHO) a good way to give huge objects to methods / objects without doing a deep copy. This saves time (interesting on embedded platforms, on the desktop, there should be enough power) and memors. Often, deep copy is not needed as the values are only read and not written. But using a reference as param, you would make it const (so the method can't change the outside value) and the in the method you need to have a deep copy for changing...

    IO like implicit shared classes much and also use them in my code.



  • As Andre says it depends upon the use case. Implicit sharing is a "Good Thing" (tm) in most cases where you want to be able to pass around a large object by value. If you are going for pure performance then using a container without implicit sharing will of course be faster since there will be no checks against reference counts being >1 etc.

    In other cases it is beneficial to use a smart pointer of some sort (e.g. QSharedPointer) this allows you to use a single object but have the reference counting handled by the pointer instead of the object itself. There are many other types of smart pointer each with their own niche use cases.

    So the answer is - it depends ;-)



  • But smart pointers do not handle copy on write, so it would be the same as a reference. Normally, you don't want methods you call to modify your objects, so you use pass by value or by const reference or const pointer.

    Implicitly shared classes solve the disadvantages of passing by value, bu adding some other things (e.g. ref counting, sync stuff for detach, etc. ).



  • [quote author="Gerolf" date="1301569763"]But smart pointers do not handle copy on write, so it would be the same as a reference.[/quote]

    Some smart pointers do implement copy on write. QSharedPointer does not but other implementations do have this - QSharedDataPointer for example.



  • QSharedDataPointer is used for implictily shared things. So it's not a difference to implicitly shared data, it's the implementatio of that patern :-)



  • Well it is part of that pattern. The other part in Qt is QSharedData. I was just trying to get across that there are different types of smart pointers for different use cases. I am still agreat fan of implicit sharing too ;-)



  • [quote author="DouglasF" date="1301566608"]My first reaction to it is that it proliferates the places in your code where you have to deal with errors such as Out of Memory. And that this completely out weighs any benefits that you get from using them. If you know you are going change the new object then you copy it once at the start and you then only have one possible failure location in your code (you also get a very marginal performance gain as you don't have all the reference counting going on). I've done several searches for 'Implicit Sharing' and I've found no mention of this issue anywhere - am I therefore missing something obvious?[/quote]

    Yes: there's no possible safe way to bail out from a OOM error except than immediately crashing the application. Therefore, that shouldn't be of your concern. The advantages are well known: less memory consumption, return-by-value made easy, and soo n. On the other hand, an implicitely shared class has a major disadvantage: due to the volatiness of the atomic counter, a sequence like:
    @
    QList<int> list(...);
    list[0] = 42;
    list[1] = 1001;
    /* ... */
    @
    actually becomes
    @
    QList<int> list(...);
    if (list->d.ref != 1) list->detach();
    list[0] = 42;
    if (list->d.ref != 1) list->detach();
    list[1] = 1001;
    @
    In case you're using implicit shared classes (Tulip containers in primis) for instance for doing expensive computations, your performance will be poor due to those (useless) checks.



  • but the checks are cheap, compared to deep copying stuff.



  • These couple of comments surprise me:

    Andre says:
    Out of memory errors are not so very likely. What’s more: handling them is neigh on impossible in many cases. That’s why they are not seen as very important, AFAIK.

    peppe says:
    Yes: there’s no possible safe way to bail out from a OOM error except than immediately crashing the application.

    Having spent many years programming for hand held devices, dealing with low and no memory was always high on the list of the way we programmed. And so was important and was effectively dealt with in many/most situations. Do you really think it is acceptable for for a word processor or spreadsheet to crash due to low memory and loose sever hours of the users work? It is very difficult to add this sort of robustness to code after you have written it - it has to be done right from the start. 'Implicit Sharing' is a very powerful and useful feature in many many situations but it can only makes it harder to add the sort of robustness to code that I'm talking about here.



  • So here we have two types of developer, handheld and desktop :-)
    Afaik Andre does mor desktop developement and not handheld, do you? And on the desktop, you normally have no memory problems if you are not dealing with really much data. But I agree, on embedded devices or handhelds, it is important.

    The robustness should be also possible with implicit sharing, why shouldn't it be possible? The only very interesting question with OOE is, what to do, if it happens? It might be that after that, a clean shutdown is even not possible anymore (depending wher it raises).



  • [quote author="Gerolf" date="1301636313"]but the checks are cheap, compared to deep copying stuff.[/quote]

    I think peppe was just saying that if you do not need implicit sharing but only raw performance for lots of numeric computations say, then a container with implicit sharing is not the best choice since those checks do have an associated cost which will not be present in a non-implicitly shared container.

    I think there was a discussion on #qt-labs recently about introducing a non-implicitly shared version of QVector for this reason.

    I think this thread can be summarised as:

    Implicit sharing is very often a good thing and it is nice that Qt provides this pattern in its containers. However, there are certain use cases where implicitly shared containers are not the best choice due to other concerns (performance, need to explicitly control deep copies etc.).



  • [quote author="Gerolf" date="1301636313"]but the checks are cheap, compared to deep copying stuff.[/quote]

    Of course -- my point was that you have no control upon them and you pay for them even if your container is not shared at all. The same thing, mutatis mutandis, applies for any implicitly shared class.

    [quote]Having spent many years programming for hand held devices, dealing with low and no memory was always high on the list of the way we programmed. And so was important and was effectively dealt with in many/most situations. Do you really think it is acceptable for for a word processor or spreadsheet to crash due to low memory and loose sever hours of the users work? It is very difficult to add this sort of robustness to code after you have written it – it has to be done right from the start[/quote]

    You're absolutely right and I wasn't disagreeing with you. My point was: when a OOM happens, there's almost nothing you can safely do except from crashing the application. Anything you do is at risk of failing again because it tries to allocate more memory.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.