Allow leaving nullptr values in VIEW::m_allItems, then defragmenting later when removing items.

Gives huge performance boost when reverting a commit.
This commit is contained in:
Alex Shvartzkop 2024-07-01 18:29:29 +03:00
parent 0904703092
commit d9929b7dff
1 changed files with 105 additions and 3 deletions

View File

@ -351,8 +351,81 @@ void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
}
static void DefragmentItems( std::vector<VIEW_ITEM*>& items )
{
size_t target = -1;
size_t sourceStart = -1;
size_t sourceEnd = -1;
for( size_t ia = 0; ia < items.size(); ia++ )
{
if( items[ia] == nullptr )
{
if( sourceStart != -1 && target != -1 && sourceEnd != -1 )
{
int len = sourceEnd - sourceStart + 1;
memmove( &items[target], &items[sourceStart], sizeof( items[0] ) * len );
target += len;
sourceStart = -1;
sourceEnd = -1;
}
if( target == -1 )
target = ia;
}
else
{
if( target != -1 )
{
if( sourceStart == -1 )
sourceStart = ia;
sourceEnd = ia;
}
}
}
if( sourceStart != -1 && target != -1 && sourceEnd != -1 )
{
int len = sourceEnd - sourceStart + 1;
memmove( &items[target], &items[sourceStart], sizeof( items[0] ) * len );
target += len;
sourceStart = -1;
sourceEnd = -1;
}
int needSize = 0;
if( target != -1 )
{
needSize = target;
}
else
{
for( int in = int( items.size() ) - 1; in >= 0; in-- )
{
if( items[in] != nullptr )
{
needSize = in + 1;
break;
}
}
}
items.resize( needSize );
}
void VIEW::Remove( VIEW_ITEM* aItem )
{
static int s_gcCounter = 0;
if( aItem && aItem->m_viewPrivData )
{
wxCHECK( aItem->m_viewPrivData->m_view == this, /*void*/ );
@ -360,8 +433,16 @@ void VIEW::Remove( VIEW_ITEM* aItem )
if( item != m_allItems->end() )
{
m_allItems->erase( item );
*item = nullptr;
aItem->m_viewPrivData->clearUpdateFlags();
s_gcCounter++;
if( s_gcCounter > 4096 )
{
DefragmentItems( *m_allItems );
s_gcCounter = 0;
}
}
int layers[VIEW::VIEW_MAX_LAYERS], layers_count;
@ -696,6 +777,9 @@ void VIEW::ReorderLayerData( std::unordered_map<int, int> aReorderMap )
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
VIEW_ITEM_DATA* viewData = item->viewPrivData();
if( !viewData )
@ -771,6 +855,9 @@ void VIEW::UpdateAllLayersColor()
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
VIEW_ITEM_DATA* viewData = item->viewPrivData();
if( !viewData )
@ -904,6 +991,9 @@ void VIEW::UpdateAllLayersOrder()
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
VIEW_ITEM_DATA* viewData = item->viewPrivData();
if( !viewData )
@ -1434,6 +1524,9 @@ void VIEW::UpdateItems()
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
auto vpd = item->viewPrivData();
if( !vpd )
@ -1472,6 +1565,9 @@ void VIEW::UpdateItems()
// and re-insert items from scratch
for( VIEW_ITEM* item : allItems )
{
if( !item )
continue;
const BOX2I bbox = item->ViewBBox();
item->m_viewPrivData->m_bbox = bbox;
@ -1497,7 +1593,7 @@ void VIEW::UpdateItems()
for( VIEW_ITEM* item : *m_allItems.get() )
{
if( item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
if( item && item->viewPrivData() && item->viewPrivData()->m_requiredUpdate != NONE )
{
invalidateItem( item, item->viewPrivData()->m_requiredUpdate );
item->viewPrivData()->m_requiredUpdate = NONE;
@ -1514,7 +1610,7 @@ void VIEW::UpdateAllItems( int aUpdateFlags )
{
for( VIEW_ITEM* item : *m_allItems )
{
if( item->viewPrivData() )
if( item && item->viewPrivData() )
item->viewPrivData()->m_requiredUpdate |= aUpdateFlags;
}
}
@ -1525,6 +1621,9 @@ void VIEW::UpdateAllItemsConditionally( int aUpdateFlags,
{
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
if( aCondition( item ) )
{
if( item->viewPrivData() )
@ -1538,6 +1637,9 @@ void VIEW::UpdateAllItemsConditionally( std::function<int( VIEW_ITEM* )> aItemFl
{
for( VIEW_ITEM* item : *m_allItems )
{
if( !item )
continue;
if( item->viewPrivData() )
item->viewPrivData()->m_requiredUpdate |= aItemFlagsProvider( item );
}