[Development] Question about QCoreApplicationData::*_libpaths

Matthew Woehlke mwoehlke.floss at gmail.com
Mon Jan 18 18:47:42 CET 2016


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.

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*.

> 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.

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 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.

> 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.

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).

(I'd be inclined to agree with such an argument, incidentally.)

-- 
Matthew




More information about the Development mailing list