Bug 303994

Summary: Many face tag comboboxes and may tags, will have an impact on performance [patch]
Product: [Applications] digikam Reporter: Kristian Karl <kristian.hermann.karl>
Component: Faces-WorkflowAssignee: Digikam Developers <digikam-bugs-null>
Status: CLOSED FIXED    
Severity: normal CC: caulier.gilles
Priority: NOR    
Version: 2.7.0   
Target Milestone: ---   
Platform: unspecified   
OS: Linux   
Latest Commit: Version Fixed In: 2.8.0
Sentry Crash Report:
Attachments: Sceenshot of an image with a lot of face tag combo boxes.
Don't sync if it's already performed

Description Kristian Karl 2012-07-24 09:07:50 UTC
Adding a lot of face tags on an image, and having a lot of tags in 'My tags', will hurt the performance of digikam.

How to reproduce:
==============
1) Start digikam, make sure you have +100 tags in 'My tags'
2) Add 2 images to a album
3) View image 1 by clicking on it (preview)
4) Enable 'Show Face Tags'
5) Manually add a 50 face tags to image 1. (Do not assign any tags, only add the face tag with the combo boxes)
6) Switch to preview image 2
7) Switch back to preview image 1
8) Repeat steps 6) and 7), and notice how the loading of image 1 gets slower and slower

I tried to troubleshoot this behavior, but did not manage to solve it. I noticed though, that digikam spent a lot of time in ModelCompletion::sync [core/libs/widgets/common/modelcompletion.cpp]
I enabled (un-commenting) the 2 kDebug() @ lines 244-245 and 260, saw what to me appeared a growth of calls to ModelCompletion::sync for each added [d->addItem(face); ==> core/utilities/facedetection/facegroup.cpp @ line 617] AssignNameWidgets. But I failed to understand why so many calls where made to ModelCompletion::sync, and from where they originated.

This never stopped growing, so that explained why digikam ran slower and slower when opening an image with a lot of AssignNameWidgets in it.

Reproducible: Always
Comment 1 Kristian Karl 2012-07-24 09:17:31 UTC
Created attachment 72721 [details]
Sceenshot of an image with a lot of face tag combo boxes.

I used this image to reproduce the problem.
The problem also occurs with images with only a few face tag combo boxes on it, it only takes longer for the problem to occur.
Comment 2 Marcel Wiesweg 2012-07-25 18:10:22 UTC
CPU or memory usage?
Comment 3 Kristian Karl 2012-07-26 09:33:32 UTC
CPU usage.
When I enabled the logging I mentioned above, I easily came to millions of calls to   ModelCompletion::sync(QAbstractItemModel* model, const QModelIndex& index) [core/libs/widgets/common/modelcompletion.cpp @ line number257]
Comment 4 Kristian Karl 2012-07-28 15:20:33 UTC
Created attachment 72805 [details]
Don't sync if it's already performed

This patch fixes the performance problem. But I'm not claiming it to be a final solution, because I do not fully understand the implications or any side effects of this patch.
Comment 5 Marcel Wiesweg 2012-07-29 12:58:28 UTC
Git commit a9aaa60c26b03e5f0b445aa78bea97fb165ebc36 by Marcel Wiesweg.
Committed on 29/07/2012 at 14:57.
Pushed by mwiesweg into branch 'master'.

Check that the new source model is not actually already the source model. Qt does not seem to make this test.

M  +9    -3    libs/models/albumfiltermodel.cpp

http://commits.kde.org/digikam/a9aaa60c26b03e5f0b445aa78bea97fb165ebc36
Comment 6 Marcel Wiesweg 2012-07-29 13:01:48 UTC
I believe this is the problem: We have 1 set of models and n completion objects. When creating each new widget, the two filter models change their source model, which resets the model, even if there is no actual change and the source model is already set. As we share the model, adding widget x will resync all 1..x completion objects, which means we will resync n + (n-1) + (n-2) + ... times.
Please check if my fix solves the problem.
Comment 7 Kristian Karl 2012-07-29 13:29:34 UTC
Yes, this solves the problem.

(In reply to comment #6)
> I believe this is the problem: We have 1 set of models and n completion
> objects. When creating each new widget, the two filter models change their
> source model, which resets the model, even if there is no actual change and
> the source model is already set. As we share the model, adding widget x will
> resync all 1..x completion objects, which means we will resync n + (n-1) +
> (n-2) + ... times.
> Please check if my fix solves the problem.