Bug 493436

Summary: Layer style + transformed clones + large canvas = extremely long file loading times.
Product: [Applications] krita Reporter: Krzysztof Jajeśnica <krzysztof.jajesnica>
Component: Layer StackAssignee: Krita Bugs <krita-bugs-null>
Status: CONFIRMED ---    
Severity: normal CC: noel, vitamorus.art
Priority: NOR    
Version First Reported In: 5.2.6   
Target Milestone: ---   
Platform: Appimage   
OS: Linux   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:
Attachments: Minimal example reproducing the problem. The file takes several minutes to open in Krita, removing the transform masks brings it down to a few seconds.

Description Krzysztof Jajeśnica 2024-09-21 13:00:02 UTC
Created attachment 173933 [details]
Minimal example reproducing the problem. The file takes several minutes to open in Krita, removing the transform masks brings it down to a few seconds.

SUMMARY

The following layer structure combined with a large canvas size cause a .kra file to take extremely long to load:

- Clone of Group 1
    - Transform mask
- (many more clones of Group 1, each with a transform mask)
- Group 1
    - Paint layer 1 with a layer style enabled.
  
This is purely a performance problem. Normally I wouldn't report something like this, but the sheer length of the resulting loading time and things which affect that loading time make me suspect that there might be be some sort of combinatorial explosion or livelock happening under the hood. 



STEPS TO REPRODUCE

1. Create a new .kra file with a somewhat large canvas size (e.g. A4 300PPI)
2. Create a group layer (let's call it "Group 1")
3. Create a paint layer (let's call it "Paint layer 1") in "Group 1" and paint something on it.
4. Add a layer style to "Paint layer 1" (tested with outer glow and drop shadow, not sure about other styles)
5. Create multiple clone layers of "Group 1". Transform each clone using a transform mask.
6. Save and close the file.
7. Attempt to open the file.



OBSERVED RESULT

The .kra file takes an extremely long time to load, on the order of several minutes (the file I've attached takes about 5 minutes on my machine). 

I've verified this is not caused by me running out of RAM and swapping to disk - I have way more than enough RAM to open the file (I've also checked Krita's memory limit just to be sure).

Removing the transform masks completely eliminates the slowdown (the file is back to loading within seconds). Disabling the layer style on "Paint layer 1" almost completely eliminates the slowdown.



EXPECTED RESULT

The .kra file takes a reasonable amount of time to load.



SOFTWARE/OS VERSIONS

OS: Debian 12 Stable, kernel 6.1.0-25-amd64
KDE Plasma Version: 5.27.5
KDE Frameworks Version: 5.103.0
Qt Version: 5.15.8



ADDITIONAL INFORMATION

Things which seem to affect the slow loading time:
- The size of the layer being cloned.
- Canvas size. Simply resizing the canvas to a larger size with the offending layer structure left completely unchanged will massively increase the loading time of the .kra file. The effect is much larger than simply resizing the canvas without having the offending layer structure present. It feels like simply having a larger canvas multiplies the slowdown created by the offending layer structure. 
- Having other layers, filters, layer styles, etc. in the same .kra file outside of the offending layer structure. Seems to have a multiplicative effect on the slowdown.

The worst case scenario is adding the offending layer structure to an existing .kra file with a large canvas size and large number of other layers. I've had it happen on a 2480x3508 image with ~100 layers. The offending part of the image was a paint layer ~600x600 in size, with an outer glow layer style. The group containing that layer was then cloned 7 times and all the clones had transform masks. This increased the loading time of the file to about 50 minutes (!). When the offending layer structure was removed, the file was back to loading in about 10 seconds.

One more thing I noticed. While a file is being loaded, Krita displays a popup with a progress bar named "Waiting for image operation". When the file contains the offending layer structure, that progress bar will jump backwards several times during the loading process. Eventually the loading process "stabilizes" and from this point the progress bar stops randomly jumping backwards, although it will progress very slowly.
- Before loading "stabilizes", Krita seems to use more than 1 CPU core (more than 100% CPU usage by the Krita process visible in top and CPU usage fluctuates wildly)
- After loading "stabilizes", Krita only seems to use a single CPU core (constant ~100% CPU usage in top)
This makes me believe there might be some sort of multithreading issue at play (I don't know the Krita codebase, this is just me speculating).

Things which don't seem to have a significant effect on the loading time:
- Filtering mode used on the transform mask. There seems to be some difference between e.g. using nearest neighbour vs something more expensive like Lanczos3, but it's not a major difference.
- How the clones are organized. I've tried all clones + original in the same group, moving the original to a separate group, organizing the clones into several groups, even having each clone in its own dedicated group. In all cases the loading time was still horribly long.
Comment 1 Vitamorus 2024-10-22 19:08:50 UTC
I can confirm this bug in 5.2.6. I believe it's known that the combination of clone and transform masks isn't very performant (a couple of threads on Krita-Artists and this report https://bugs.kde.org/show_bug.cgi?id=388545) and I would guess this is related.  Perhaps the non-destructive properties of the nodes sends Krita into a long recursive chain when generating the image?
Comment 2 Noel Santos 2025-06-26 18:53:29 UTC
I have encountered similar issues when trying to create some effects like a long shadow by stacking drop shadows in 5.2.9 (see https://www.virtualcuriosities.com/articles/5346/how-to-create-a-diagonal-long-shadow-effect-in-krita ). Granted that I had a dozen clones of clones of clones, but it still seemed to take a ridiculously long amount of time for how simple the layer structure was, specially considering that opening the layer styles dialog requires a full render first for some reason.

I have no idea how Krita is programmed but my assumption is that Krita isn't applying the filters/layer styles like a node-based non-linear editor would, by going one step then the next. Instead, it seems to iterate for every renderable "cell" on the canvas and try to figure out the pixels of that cell. Presumably this is optimized for painting so it can blend hundreds of layers in parallel, but when you use effects there seems to be no optimization. Based on this, my completely uneducated guess is that Krita is going to a cell, rendering the entire effect, then cropping it to the cell, then going to the next cell and rendering it all over again, instead of just reusing the data. That's the only algorithm I can imagine that would lead to this kind of performance issue.

I believe Krita has a lot of potential with these non-destructive features, so it's really unfortunate that bugs like these prevent Krita from being used to its full potential. For now I recommend workarounds like merging a group layer, selecting it, copying, undoing, and pasting the copied data to use it in an effect, manually refreshing it from time to time, since waiting the filters/styles to apply takes just far too long. You can also keep effects in a separate group with pass through that you can make invisible to prevent Krita from rendering them.