Skip to content

Commit 4181183

Browse files
committed
Performance optimizations around UI
- various improvements - lazily creates the UI wigets for categories when their parent is expanded
1 parent 55931a2 commit 4181183

File tree

7 files changed

+213
-84
lines changed

7 files changed

+213
-84
lines changed

indra/llcommon/llsingleton.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -522,13 +522,16 @@ class LLSingleton : public LLSingletonBase
522522
case INITIALIZING:
523523
// here if DERIVED_TYPE::initSingleton() (directly or indirectly)
524524
// calls DERIVED_TYPE::getInstance(): go ahead and allow it
525-
case INITIALIZED:
526-
// normal subsequent calls
527-
// record the dependency, if any: check if we got here from another
525+
// record the dependency: check if we got here from another
528526
// LLSingleton's constructor or initSingleton() method
529527
capture_dependency(lk->mInstance);
530528
return lk->mInstance;
531529

530+
case INITIALIZED:
531+
// normal subsequent calls - skip capture_dependency() for performance
532+
// dependencies are only tracked during initialization
533+
return lk->mInstance;
534+
532535
case DELETED:
533536
// called after deleteSingleton()
534537
logwarns({"Trying to access deleted singleton ",
@@ -728,12 +731,14 @@ class LLParamSingleton : public LLSingleton<DERIVED_TYPE>
728731

729732
case super::INITIALIZING:
730733
// As with LLSingleton, explicitly permit circular calls from
731-
// within initSingleton()
732-
case super::INITIALIZED:
733-
// for any valid call, capture dependencies
734+
// within initSingleton() and capture dependencies
734735
super::capture_dependency(lk->mInstance);
735736
return lk->mInstance;
736737

738+
case super::INITIALIZED:
739+
// normal subsequent calls - skip capture_dependency() for performance
740+
return lk->mInstance;
741+
737742
case super::DELETED:
738743
super::logerrs({"Trying to access deleted param singleton ",
739744
super::template classname<DERIVED_TYPE>()});

indra/llui/llpanel.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -489,58 +489,70 @@ bool LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
489489
LL_RECORD_BLOCK_TIME(FTM_PANEL_SETUP);
490490

491491
LLXMLNodePtr referenced_xml;
492-
std::string xml_filename = mXMLFilename;
492+
const std::string& xml_filename = mXMLFilename;
493493

494494
// if the panel didn't provide a filename, check the node
495495
if (xml_filename.empty())
496496
{
497-
node->getAttributeString("filename", xml_filename);
498-
setXMLFilename(xml_filename);
497+
std::string temp_filename;
498+
node->getAttributeString("filename", temp_filename);
499+
setXMLFilename(temp_filename);
499500
}
500501

502+
// Cache singleton and filename to avoid repeated calls
503+
LLUICtrlFactory* factory = LLUICtrlFactory::getInstance();
504+
505+
// Cache node name pointer to avoid repeated dereferencing
506+
const LLStringTableEntry* node_name = node->getName();
507+
508+
// Cache registry to avoid repeated singleton access
509+
const child_registry_t& registry = child_registry_t::instance();
510+
501511
LLXUIParser parser;
502512

503-
if (!xml_filename.empty())
513+
if (!mXMLFilename.empty())
504514
{
505515
if (output_node)
506516
{
507517
//if we are exporting, we want to export the current xml
508518
//not the referenced xml
509-
parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
519+
parser.readXUI(node, params, factory->getCurFileName());
510520
Params output_params(params);
511521
setupParamsForExport(output_params, parent);
512-
output_node->setName(node->getName()->mString);
522+
output_node->setName(node_name->mString);
513523
parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
514524
return true;
515525
}
516526

517-
LLUICtrlFactory::instance().pushFileName(xml_filename);
527+
factory->pushFileName(mXMLFilename);
518528

519529
LL_RECORD_BLOCK_TIME(FTM_EXTERNAL_PANEL_LOAD);
520-
if (!LLUICtrlFactory::getLayeredXMLNode(xml_filename, referenced_xml))
530+
if (!LLUICtrlFactory::getLayeredXMLNode(mXMLFilename, referenced_xml))
521531
{
522-
LL_WARNS() << "Couldn't parse panel from: " << xml_filename << LL_ENDL;
532+
LL_WARNS() << "Couldn't parse panel from: " << mXMLFilename << LL_ENDL;
523533

524534
return false;
525535
}
526536

527-
parser.readXUI(referenced_xml, params, LLUICtrlFactory::getInstance()->getCurFileName());
537+
// Get filename after pushFileName
538+
const std::string& updated_filename = factory->getCurFileName();
539+
parser.readXUI(referenced_xml, params, updated_filename);
528540

529541
// add children using dimensions from referenced xml for consistent layout
530542
setShape(params.rect);
531-
LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
543+
LLUICtrlFactory::createChildren(this, referenced_xml, registry);
532544

533-
LLUICtrlFactory::instance().popFileName();
545+
factory->popFileName();
534546
}
535547

536548
// ask LLUICtrlFactory for filename, since xml_filename might be empty
537-
parser.readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
549+
parser.readXUI(node, params, factory->getCurFileName());
538550

539551
if (output_node)
540552
{
541553
Params output_params(params);
542554
setupParamsForExport(output_params, parent);
543-
output_node->setName(node->getName()->mString);
555+
output_node->setName(node_name->mString);
544556
parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
545557
}
546558

@@ -552,7 +564,7 @@ bool LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
552564
}
553565

554566
// add children
555-
LLUICtrlFactory::createChildren(this, node, child_registry_t::instance(), output_node);
567+
LLUICtrlFactory::createChildren(this, node, registry, output_node);
556568

557569
// Connect to parent after children are built, because tab containers
558570
// do a reshape() on their child panels, which requires that the children

indra/llui/llview.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,12 @@ bool LLView::addChild(LLView* child, S32 tab_group)
305305
// add to front of child list, as normal
306306
mChildList.push_front(child);
307307

308+
// Add to name cache for fast lookup
309+
if (!child->getName().empty())
310+
{
311+
mChildNameCache[child->getName()] = child;
312+
}
313+
308314
// add to tab order list
309315
if (tab_group != 0)
310316
{
@@ -344,6 +350,13 @@ void LLView::removeChild(LLView* child)
344350
// if we are removing an item we are currently iterating over, that would be bad
345351
llassert(!child->mInDraw);
346352
mChildList.remove( child );
353+
354+
// Remove from name cache
355+
if (!child->getName().empty())
356+
{
357+
mChildNameCache.erase(child->getName());
358+
}
359+
347360
child->mParentView = NULL;
348361
child_tab_order_t::iterator found = mTabOrder.find(child);
349362
if (found != mTabOrder.end())
@@ -1649,15 +1662,25 @@ LLView* LLView::findChildView(std::string_view name, bool recurse) const
16491662
{
16501663
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
16511664

1665+
// Check cache first for direct children - O(1) lookup instead of O(n)
1666+
auto cache_it = mChildNameCache.find(name);
1667+
if (cache_it != mChildNameCache.end())
1668+
{
1669+
return cache_it->second;
1670+
}
1671+
16521672
// Look for direct children *first*
16531673
for (LLView* childp : mChildList)
16541674
{
16551675
llassert(childp);
16561676
if (childp->getName() == name)
16571677
{
1678+
// Cache the result for next lookup
1679+
mChildNameCache[name] = childp;
16581680
return childp;
16591681
}
16601682
}
1683+
16611684
if (recurse)
16621685
{
16631686
// Look inside each child as well.

indra/llui/llview.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,9 @@ class LLView
589589
LLView* mParentView;
590590
child_list_t mChildList;
591591

592+
// Cache for fast child lookup by name - O(1) instead of O(n)
593+
mutable std::unordered_map<std::string_view, LLView*> mChildNameCache;
594+
592595
// location in pixels, relative to surrounding structure, bottom,left=0,0
593596
bool mVisible;
594597
LLRect mRect;

0 commit comments

Comments
 (0)