PDA

View Full Version : Why does QDateTime allocate its internal QDate and QTime pair on the heap?



Oibaf
14th July 2017, 21:54
Hi all,

I am using QDateTime extensively in a series of procedures that need to run as fast as possible, under 250 milliseconds in total, therefore I really want to avoid heap allocations as much as possible.

However, I just realized that QDateTime allocates its internals on the heap, sharing them with other QDateTime objects until they are modified. This might be fine when the datetime object gets just passed around, but it seems overkill when lots of operations have to be done on it, resulting in multiple temporary copies and therefore multiple temporary heap allocations.

To be totally honest I've not done any extensive profiling to determine whether this is in reality an issue, but just in case I find that the heap allocations really waste too much time, what obstacles do you think there would be in building a QDateTime-alike class that embedded directly in itself a pair of QDate and QTime objects, providing the same interface as QDateTime's?

Has this ever been done before?

Infinity
15th July 2017, 02:18
Allocating the internals on the heap has the advantage that the member variables can be modified or extended without breaking the ABI. This so called D-Pointer-pattern (http://wiki.qt.io/D-Pointer) is actually used by a lot of classes in the Qt framework.

In theory is would be possible to implement any of these classes without using that pattern. It is really just about ABI compatibility.


Has this ever been done before?

I once created my own DateTime and TimeSpan classes: https://github.com/Martchus/cpp-utilities/blob/master/chrono
It is very lightweight because it uses only a 64-bit int and no further heap allocations. However, its interface is different from QDateTime.

Oibaf
15th July 2017, 07:37
Allocating the internals on the heap has the advantage that the member variables can be modified or extended without breaking the ABI. This so called D-Pointer-pattern is actually used by a lot of classes in the Qt framework.

Yeah, I'm aware of that pattern in general, it just seems overkill in this case, given that QDateTime is a little more than an aggregate of a QDate and QTime, and that QDate and QTime themselves don't use such a pattern: is the ABI really important in this case? Why?

Thanks for the pointer to your code!

Infinity
15th July 2017, 20:22
If you look at the code QDateTime is a little bit more complex:



qint64 m_msecs;
StatusFlags m_status;
int m_offsetFromUtc;
mutable QAtomicInt ref;
#if QT_CONFIG(timezone)
QTimeZone m_timeZone;
#endif // timezone


The QDateTime class with all its additional features like status and time zone information seems to be complex enough for Qt developers to assume that future changes might require modifying member variables. Hence they chose the D-Pointer pattern to allow those changes without breaking ABI. Preserving the ABI is important for all parts of the Qt libs (except some 'private' parts, eg. the API for writing QPA-plugins).

However, I also find that QDateTime class is a bit of an overkill. Additionally, it lacks a 'TimeSpan' class. So I usually use my own classes which I actually wrote to learn C++.