Is Implicit Sharing always a good thing?
-
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.
-
[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. -
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.