Re: KFileItem (Re: Jenkins build became unstable: kdelibs_frameworks_qt5 #982)

2013-08-23 Thread Frank Reininghaus
Hi,

2013/8/22 David Faure:
> On Thursday 08 August 2013 13:17:18 Frank Reininghaus wrote:
>> Hi David,
>>
>> 2013/8/7 David Faure:
>> > On Tuesday 06 August 2013 20:53:05 Frank Reininghaus wrote:
>> >> OK, I see now that it uses pointers to be able to modify the actual
>> >> KFileItems in KDirListerCache (if it would just keep KFileItems and
>> >> modify these, I guess that they would just detach from the ones inside
>> >> the cache, leaving those unchanged).
>> >
>> > Yes.
>> >
>> >
>> > I suppose a solution would be to use a QLinkedList in KDirListerCache.
>> > This
>> > would basically cancel the Q_MOVABLE_TYPE for that particular list (since
>> > it would need to allocate nodes), but every other KFileItemList out there
>> > would still benefit.
>>
>> But it would also slow down things when KDirListerCache has to convert
>> its internal data to KFileItemLists when emitting signals. Hm, I'll
>> try to find some time to think about it and see if there is a good
>> solution. I was going to have a close look at KDirListerCache anyway
>> because I have the impression that the remaining sources of O(N^2)
>> behavior in Dolphin when adding/removing many items to a directory in
>> weird ways are in this class.
>
> Yeah, conversions would not be great. But I don't see where you think
> conversions would happen. The KFileItemList emitted by "itemsAdded" is created
> item by item anyway, in addNewItem(). It's not like we can take the list that
> is used as storage in KDirLister and emit that, since we only want to emit the
> *new* items, not all of them (everything is async and incremental).

OK, you're probably right. I had thought that copying the items from
one KFileItemList to another KFileItemList is cheaper than iterating
through a linked list, but that's probably wrong if the KFileItemList
only keeps pointers to the actual items. I'll try to find some time to
check that at some point.

>> >> It looks like a solution for this problem is more complicated than I
>> >> thought, so maybe I'll just revert the commit to make Jenkins happy
>> >> again. However, I still think that making KFileItem a Q_MOVABLE_TYPE
>> >> might be a desirable long-term goal because it saves quite a bit of
>> >> memory (32 bytes per KFileItem on my system).
>> >
>> > 32 *bytes* ? Are you sure? I think you meant 32 bits?
>>
>> Yes, I am sure, see below.
>>
>> > In fact I'm surprised. sizeof(KFileItem) = sizeof(void*), right? So QList
>> > should already lay out the kfileitems next to each other in memory, the
>> > only issue is that insertion makes copies, but I don't see where a memory
>> > saving happens. I thought QList only wasted memory for types bigger than
>> > a pointer (in which case it had to allocate nodes) ?
>>
>> AFAIK, QList only puts items of type T next to each other in memory if
>> sizeof(T) <= sizeof(void*) *and* T is a Q_MOVABLE_TYPE.
>
> Seems right.
>
>> If that is not
>> the case, QList only stores T* pointers next to each other in one
>> block of memory.
>
> Yes, which means taking the size of one pointer more, i.e. 8 bytes per item.
> Not 32.

But the memory allocator needs a considerable amount of memory for
internal use, see below.

>> I guess the reason for this design decision is that
>> this permits QList to share the same core code (which uses memcpy
>> to move around items in memory), no matter what T is.
>
> It's mainly an optimization: as you saw, when items are small enough,
> replacing pointers with the item itself is a saving, not only in memory usage,
> but also in speed since the data is much closer together (=less memory pages
> to load). But if the data is bigger than a pointer, then it doesn't fit in
> what was originally sized to contain a pointer.
>
> For putting large items in contiguous memory, there's QVector.
>
>> Also my experimental findings in
>> https://git.reviewboard.kde.org/r/111789/ support that. According to
>> massif/massif-visualizer, a simple program that creates a
>> KFileItemList with 1 million Q_MOVABLE null KFileItems needs about 8
>> MB (is to be expected because that's what you need for 1 million
>> pointers on my 64-bit system). However, without Q_MOVABLE_TYPE, i.e.,
>> with the current master or frameworks branch, it needs 16 MB because
>> the list only stores KFileItem* pointers in the 8 MB block, and the
>> memory for the items themselves is allocated with 1 million calls of
>> "new KFileItem" -> 8 MB more.
>>
>> However, this is only the net memory usage. In reality, the memory
>> allocator also needs some memory for its own bookkeeping, and it thus
>> adds a bit of overhead to any memory allocation with new or malloc.
>> With KSysGuard, I found that the difference in memory consumption for
>> my test program with/without Q_MOVABLE_TYPE is a bit more than 30.5
>> MiB, and if you take into account that 1 MiB = 1024*1024 bytes, and my
>> test used 1 million = 10^6 KFileItems, this looks pretty much like
>> every "new KFileItem" occupies 32 bytes. And this is a bit too 

Re: KFileItem (Re: Jenkins build became unstable: kdelibs_frameworks_qt5 #982)

2013-08-22 Thread David Faure
On Thursday 08 August 2013 13:17:18 Frank Reininghaus wrote:
> Hi David,
> 
> 2013/8/7 David Faure:
> > On Tuesday 06 August 2013 20:53:05 Frank Reininghaus wrote:
> >> OK, I see now that it uses pointers to be able to modify the actual
> >> KFileItems in KDirListerCache (if it would just keep KFileItems and
> >> modify these, I guess that they would just detach from the ones inside
> >> the cache, leaving those unchanged).
> > 
> > Yes.
> > 
> > 
> > I suppose a solution would be to use a QLinkedList in KDirListerCache.
> > This
> > would basically cancel the Q_MOVABLE_TYPE for that particular list (since
> > it would need to allocate nodes), but every other KFileItemList out there
> > would still benefit.
> 
> But it would also slow down things when KDirListerCache has to convert
> its internal data to KFileItemLists when emitting signals. Hm, I'll
> try to find some time to think about it and see if there is a good
> solution. I was going to have a close look at KDirListerCache anyway
> because I have the impression that the remaining sources of O(N^2)
> behavior in Dolphin when adding/removing many items to a directory in
> weird ways are in this class.

Yeah, conversions would not be great. But I don't see where you think 
conversions would happen. The KFileItemList emitted by "itemsAdded" is created 
item by item anyway, in addNewItem(). It's not like we can take the list that 
is used as storage in KDirLister and emit that, since we only want to emit the 
*new* items, not all of them (everything is async and incremental).

> >> It looks like a solution for this problem is more complicated than I
> >> thought, so maybe I'll just revert the commit to make Jenkins happy
> >> again. However, I still think that making KFileItem a Q_MOVABLE_TYPE
> >> might be a desirable long-term goal because it saves quite a bit of
> >> memory (32 bytes per KFileItem on my system).
> > 
> > 32 *bytes* ? Are you sure? I think you meant 32 bits?
> 
> Yes, I am sure, see below.
> 
> > In fact I'm surprised. sizeof(KFileItem) = sizeof(void*), right? So QList
> > should already lay out the kfileitems next to each other in memory, the
> > only issue is that insertion makes copies, but I don't see where a memory
> > saving happens. I thought QList only wasted memory for types bigger than
> > a pointer (in which case it had to allocate nodes) ?
> 
> AFAIK, QList only puts items of type T next to each other in memory if
> sizeof(T) <= sizeof(void*) *and* T is a Q_MOVABLE_TYPE. 

Seems right.

> If that is not
> the case, QList only stores T* pointers next to each other in one
> block of memory. 

Yes, which means taking the size of one pointer more, i.e. 8 bytes per item.
Not 32.

> I guess the reason for this design decision is that
> this permits QList to share the same core code (which uses memcpy
> to move around items in memory), no matter what T is.

It's mainly an optimization: as you saw, when items are small enough, 
replacing pointers with the item itself is a saving, not only in memory usage, 
but also in speed since the data is much closer together (=less memory pages 
to load). But if the data is bigger than a pointer, then it doesn't fit in 
what was originally sized to contain a pointer.

For putting large items in contiguous memory, there's QVector.

> Also my experimental findings in
> https://git.reviewboard.kde.org/r/111789/ support that. According to
> massif/massif-visualizer, a simple program that creates a
> KFileItemList with 1 million Q_MOVABLE null KFileItems needs about 8
> MB (is to be expected because that's what you need for 1 million
> pointers on my 64-bit system). However, without Q_MOVABLE_TYPE, i.e.,
> with the current master or frameworks branch, it needs 16 MB because
> the list only stores KFileItem* pointers in the 8 MB block, and the
> memory for the items themselves is allocated with 1 million calls of
> "new KFileItem" -> 8 MB more.
> 
> However, this is only the net memory usage. In reality, the memory
> allocator also needs some memory for its own bookkeeping, and it thus
> adds a bit of overhead to any memory allocation with new or malloc.
> With KSysGuard, I found that the difference in memory consumption for
> my test program with/without Q_MOVABLE_TYPE is a bit more than 30.5
> MiB, and if you take into account that 1 MiB = 1024*1024 bytes, and my
> test used 1 million = 10^6 KFileItems, this looks pretty much like
> every "new KFileItem" occupies 32 bytes. And this is a bit too much
> for my taste ;-)

It's not that I don't trust you or these tools, but I would like to see an 
explanation of the "32 bytes" from the code rather than from high-level 
measurements. I can understand "losing" 8 bytes per item, but not 32.

-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Working on KDE, in particular KDE Frameworks 5

___
Kde-frameworks-devel mailing list
Kde-frameworks-devel@kde.org
https://mail.kde.org/mailman/listinfo/kde-framework

Re: KFileItem (Re: Jenkins build became unstable: kdelibs_frameworks_qt5 #982)

2013-08-08 Thread Frank Reininghaus
Hi David,

2013/8/7 David Faure:
> On Tuesday 06 August 2013 20:53:05 Frank Reininghaus wrote:
>> OK, I see now that it uses pointers to be able to modify the actual
>> KFileItems in KDirListerCache (if it would just keep KFileItems and
>> modify these, I guess that they would just detach from the ones inside
>> the cache, leaving those unchanged).
>
> Yes.
>
>
> I suppose a solution would be to use a QLinkedList in KDirListerCache. This
> would basically cancel the Q_MOVABLE_TYPE for that particular list (since it
> would need to allocate nodes), but every other KFileItemList out there would
> still benefit.

But it would also slow down things when KDirListerCache has to convert
its internal data to KFileItemLists when emitting signals. Hm, I'll
try to find some time to think about it and see if there is a good
solution. I was going to have a close look at KDirListerCache anyway
because I have the impression that the remaining sources of O(N^2)
behavior in Dolphin when adding/removing many items to a directory in
weird ways are in this class.

>> It looks like a solution for this problem is more complicated than I
>> thought, so maybe I'll just revert the commit to make Jenkins happy
>> again. However, I still think that making KFileItem a Q_MOVABLE_TYPE
>> might be a desirable long-term goal because it saves quite a bit of
>> memory (32 bytes per KFileItem on my system).
>
> 32 *bytes* ? Are you sure? I think you meant 32 bits?

Yes, I am sure, see below.

> In fact I'm surprised. sizeof(KFileItem) = sizeof(void*), right? So QList
> should already lay out the kfileitems next to each other in memory, the only
> issue is that insertion makes copies, but I don't see where a memory saving
> happens. I thought QList only wasted memory for types bigger than a pointer
> (in which case it had to allocate nodes) ?

AFAIK, QList only puts items of type T next to each other in memory if
sizeof(T) <= sizeof(void*) *and* T is a Q_MOVABLE_TYPE. If that is not
the case, QList only stores T* pointers next to each other in one
block of memory. I guess the reason for this design decision is that
this permits QList to share the same core code (which uses memcpy
to move around items in memory), no matter what T is.

Also my experimental findings in
https://git.reviewboard.kde.org/r/111789/ support that. According to
massif/massif-visualizer, a simple program that creates a
KFileItemList with 1 million Q_MOVABLE null KFileItems needs about 8
MB (is to be expected because that's what you need for 1 million
pointers on my 64-bit system). However, without Q_MOVABLE_TYPE, i.e.,
with the current master or frameworks branch, it needs 16 MB because
the list only stores KFileItem* pointers in the 8 MB block, and the
memory for the items themselves is allocated with 1 million calls of
"new KFileItem" -> 8 MB more.

However, this is only the net memory usage. In reality, the memory
allocator also needs some memory for its own bookkeeping, and it thus
adds a bit of overhead to any memory allocation with new or malloc.
With KSysGuard, I found that the difference in memory consumption for
my test program with/without Q_MOVABLE_TYPE is a bit more than 30.5
MiB, and if you take into account that 1 MiB = 1024*1024 bytes, and my
test used 1 million = 10^6 KFileItems, this looks pretty much like
every "new KFileItem" occupies 32 bytes. And this is a bit too much
for my taste ;-)

Best regards,
Frank
___
Kde-frameworks-devel mailing list
Kde-frameworks-devel@kde.org
https://mail.kde.org/mailman/listinfo/kde-frameworks-devel


KFileItem (Re: Jenkins build became unstable: kdelibs_frameworks_qt5 #982)

2013-08-07 Thread David Faure
On Tuesday 06 August 2013 20:53:05 Frank Reininghaus wrote:
> OK, I see now that it uses pointers to be able to modify the actual
> KFileItems in KDirListerCache (if it would just keep KFileItems and
> modify these, I guess that they would just detach from the ones inside
> the cache, leaving those unchanged).

Yes.


I suppose a solution would be to use a QLinkedList in KDirListerCache. This 
would basically cancel the Q_MOVABLE_TYPE for that particular list (since it 
would need to allocate nodes), but every other KFileItemList out there would 
still benefit.

> It looks like a solution for this problem is more complicated than I
> thought, so maybe I'll just revert the commit to make Jenkins happy
> again. However, I still think that making KFileItem a Q_MOVABLE_TYPE
> might be a desirable long-term goal because it saves quite a bit of
> memory (32 bytes per KFileItem on my system).

32 *bytes* ? Are you sure? I think you meant 32 bits?

In fact I'm surprised. sizeof(KFileItem) = sizeof(void*), right? So QList 
should already lay out the kfileitems next to each other in memory, the only 
issue is that insertion makes copies, but I don't see where a memory saving 
happens. I thought QList only wasted memory for types bigger than a pointer 
(in which case it had to allocate nodes) ?

-- 
David Faure, fa...@kde.org, http://www.davidfaure.fr
Working on KDE, in particular KDE Frameworks 5

___
Kde-frameworks-devel mailing list
Kde-frameworks-devel@kde.org
https://mail.kde.org/mailman/listinfo/kde-frameworks-devel