BR: TreeView performance is so bad it's unusable

This is a release build running on a Apple M1. You can see the scrolling starts off smooth, but the further you scroll, the slower it gets until it can’t even do 1 fps. If there are enough items, eventually it gets so bad the OS thinks the app has stopped responding.

Code: juce_bugs/TreeViewPerf/Source/MainComponent.cpp at master · FigBug/juce_bugs · GitHub

5 Likes

Here is a non-insane implementation of getAllVisibleItems() that is O(n) instead of O(n*n). Same behaviour as the original that finds the visible items plus 4 extra.

    std::vector<TreeViewItem*> getAllVisibleItems() const
    {
        if (owner.rootItem == nullptr)
            return {};

        const auto visibleTop = -getY();
        const auto visibleBottom = visibleTop + getParentHeight();

        std::vector<TreeViewItem*> allItems;
        std::vector<TreeViewItem*> visibleItems;
                
        std::function<void (TreeViewItem*)> findItems;
        
        findItems = [&] (TreeViewItem* itm)
        {
            if (itm != owner.rootItem || owner.rootItemVisible)
                allItems.push_back (itm);
            
            if (itm->isOpen())
                for (int i = 0; i < itm->getNumSubItems(); i++)
                    findItems (itm->getSubItem (i));
        };
        
        findItems (owner.rootItem);
        
        std::optional<int> firstIndex;
        std::optional<int> lastIndex;
        
        for (size_t i = 0; i < allItems.size(); i++)
        {
            auto itm = allItems[i];
            
            if (itm->y + itm->itemHeight > visibleTop && itm->y < visibleBottom)
            {
                visibleItems.push_back (itm);
                if (! firstIndex.has_value()) firstIndex = int (i);
                lastIndex = int (i);
            }
        }
        
        if (firstIndex.has_value())
        {
            if (*firstIndex - 1 >= 0) 
                visibleItems.insert (visibleItems.begin(), allItems[size_t (*firstIndex - 1)]);
            
            if (*firstIndex - 2 >= 0)
                visibleItems.insert (visibleItems.begin(), allItems[size_t (*firstIndex - 2)]);
        }
        
        if (lastIndex.has_value())
        {
            if (*lastIndex + 1 < int (allItems.size())) 
                visibleItems.push_back (allItems[size_t (*lastIndex + 1)]);
            
            if (*lastIndex + 2 < int (allItems.size()))
                visibleItems.push_back (allItems[size_t (*lastIndex + 2)]);
        }
        
        return visibleItems;
    }
11 Likes

+1 for just giving Roland commit rights to JUCE
develop, can’t pay for better bug reports (including fixes)! Feeling grateful :smiling_face_with_three_hearts:

1 Like

Would be awesome if @RolandMR would have a JUCE fork with fixes ready so we can cherry-pick. Or is there one that u didn’t find?

I would also like to thank you for all the contributions. Are the bugs in the juce_bugs repo generally fixed in the reFX fork?

Depends which of my clients I fixed the bug for, they will either appear in GitHub - reFX/JUCE: The JUCE cross-platform C++ framework or GitHub - Tracktion/JUCE: The JUCE cross-platform C++ framework

In this case, the fix is here: tracktion: TreeView improve performance · Tracktion/JUCE@b5b5dee · GitHub

1 Like

We certainly appreciate the bug reports and fixes! However, no-one gets to push directly to develop, not even JUCE employees. Each commit needs to be reviewed by at least one other team-member, and pass our CI pipeline. We can try to get this fix merged soon, but unfortunately most of our time is currently being spent preparing JUCE 8.

2 Likes

You should consider making the tests (or at least a subset) run on GitHub Actions. It would make it a lot easier for those submitting patches to know if it compiles cleanly on all platform for example.

6 Likes

Heh, that’s all a good thing! Don’t mind me, just being effusive in my support for Roland.

Good luck whipping 8 into shape!

I would love this too. I brought up the possibility a couple ADCs ago (when I was enthusiastically porting everything to GitHub Actions).

2 Likes

Please keep this conversation on the topic of TreeView performance and away from derogatory cartoons about the JUCE team.

https://forum.juce.com/guidelines

6 Likes

Fair enough to bring the conversation back to the original topic, but I see no derogatory behaviour above. The conversation seemed nice and respectful of the JUCE team while providing (hopefully constructive) feedback.

Current Treeviews feel clunky (for a lack of a better term, I am not a native speaker) to me too. +1 for improving their performance when the time comes.

Suspect it was removed.
But yes, the treeview deserves some TLC. Hopefully rather sooner then later.

Oh, I haven’t thought of that, makes sense.

Thanks for reporting, the issue should be resolved here:

6 Likes