[Development] Question about QCoreApplicationData::*_libpaths

Bubke Marco Marco.Bubke at theqtcompany.com
Mon Jan 18 19:40:02 CET 2016


Hi Matthew, 

Your whole point was relocation but my point was traversing. Relocation can be easily fixed by reserve but if traversing is slow it is much harder to remove the convenience structures. I don't say we should not provide them, I only say they should be on top. 

On January 18, 2016 18:48:07 Matthew Woehlke <mwoehlke.floss at gmail.com> wrote:

> On 2016-01-16 07:06, Bubke Marco wrote:
>> On January 16, 2016 06:08:14 Kevin Kofler wrote:
>>> I suspect we would lose at least some optimizations from 
>>> Q_DECLARE_TYPEINFO.
>> 
>> std::is_trivially_copyable and other type traits are your friends.
>
> Not really. There is a huge difference between a relocatable type (many,
> if not most), and a trivially copyable type (a lot fewer). Operations
> such as growing the buffer can be vastly more expensive if the item type
> is not relocatable vs. if it is. However, C++ itself currently does not
> provide any support for relocation.

So how many people define there objects as relocatable? Anyway for large vectors I use always reserve which is a quite common optimization. For pattern were you are holding references in the vector you have to do it anyway. 

> I want to say e.g. std::string is relocatable, but it is certainly not
> trivially copyable. Now, imagine a std::vector<std::string> where both
> the vector and strings are very large. When the vector needs to resize,
> it will have to do a deep copy of ever single item, allocating and
> freeing lots of memory in the process. Compare to QVector<std::string>
> (assume Q_DECLARE_TYPEINFO declares std::string relocatable), which...
> will do a realloc(). Worst case, that's 1 alloc, 1 free, and 1 block
> copy... and 0 ctor/dtor calls.
>
> That's a *significant* difference.
>
> (Even using QString instead of std::string does not help much... the
> QVector still just does a realloc, while std::vector must perform 2*N
> atomic operations.)
>
> ...and then there's QList, which just does a realloc(), *always*.

So you optimized the container for growing with allocations. I don't think it is the most common case. Having cache misses in traversing the container can be much worse and is much harder to fix than a reserve. 

>
>> There are other pitfalls in the qt containers,  e.g.
>> 
>> if (container.contains(key)) 
>>    auto value = container.value(key);
>> 
>> auto iterator = container.find(key);
>> if (iterator! = container.den()) 
>>   auto value = iterator.value();
>> 
>> The first looks nice but leads to two lookups. And I have seen it very often. 
>
> Probably because a) it's easier / clearer to read, b) it's MUCH easier
> to write, and c) most of the time the performance doesn't matter enough
> to justify the ugliness of the latter. Specifically, I know I have
> written code like that *in full knowledge* that it's inefficient, simply
> because I don't judge it sufficiently inefficient to justify the ugly
> and obtuse STL syntax.

I don't think it's is so obscure. In Qt we have many obscure patters too but you adapt to it. As I was coming from python I found Qt ugly but it changed with time. ;-)

> That said, the *correct* fix is:
>
>   auto value = container.maybe_at(key);
>   if (value)
>     do_something(*value);
>
> (...using std::optional or similar)
>
> This is easy to read, easy to write, *and* efficient.

I would prefer ranges. I think the next big step is easy writable parallel algorithms and hand written code like that is in my opinion not that maintainable. But we will see. 

>> I understand the problem. But my problem is more that I have the
>> atomic pointer which can slow your code done unexpectedly.
>
> Compared to what? The pointer only kicks in during a copy or destroy. At
> the point of the copy, the question is if a deep copy is slower than an
> atomic operation. At the point of destruction, you are probably slow
> anyway, though if it's just a dereference, you have potentially saved a
> heap free.

What about begin? Sorry, why are many other moving away from CoW for small data structures? Do we know something what they are not knowing? Atomics with multi cores can slow down your code considerable so copying can be smarter in that case. 

>> If you provide data structures which are trivially copy able the
>> simply could be moved in memory for a vector which is quite fast.
>
> ...except not nearly so many data structures are trivially copyable as
> you would like to think. Many are *relocatable* (a concept that does not
> yet exist in C++ proper), but *not* trivially copyable.

Actually many of my demanding structures are trivially copyable.  ;-)

> Even move semantics are less efficient than relocation (usually not by
> much, but still by some).
>
>> I don't say that there is no use case for a pointed vector but I can always do
>> Vector<Entry*>
>
> No, you can't. At best, you'd have to do vector<unique_ptr<Entry>>, and
> you'd still have a leaky abstraction problems. Having the indirection
> built into the container shields you from this.
>
> At best, this seems like an argument that QList should act like QVector
> for relocatable types up to a certain size (said size being greater than
> a single pointer, as is currently the case).

Actually I don't like that magic. You optimising a data structure for one use cases which is in many cases easily fixable. I don't think relocation is the most common problem. 

> (I'd be inclined to agree with such an argument, incidentally.)
>
> -- 
> Matthew
>
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

--
Sent from cellphone, sorry for the typos



More information about the Development mailing list