Another performance optimization to "extresist", this one to

avoid re-parsing a linked list from the current breakpoint
to the end to find all entries pointing to the same node.
Instead, the change to be made is saved in a hash table and
applied at the following link, so only one pass through the
linked list is required.
This commit is contained in:
R. Timothy Edwards 2026-05-21 19:55:50 -04:00
parent a062fdcfe0
commit 7a3717b02a
3 changed files with 100 additions and 29 deletions

View File

@ -1 +1 @@
8.3.646
8.3.647

View File

@ -125,7 +125,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
resNode **pendingList, **doneList;
resResistor **resList;
{
int height;
int count, height;
bool merged;
TileType ttype;
Breakpoint *p1, *p2, *p3;
@ -134,6 +134,8 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
resNode *currNode;
float rArea;
resInfo *info = (resInfo *)TiGetClientPTR(tile);
HashTable BreakTable;
HashEntry *he;
merged = FALSE;
height = TOP(tile) - BOTTOM(tile);
@ -163,21 +165,38 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
ttype = TiGetTypeExact(tile);
/* Re-sort nodes left to right. */
count = ResSortBreaks(&info->breakList, TRUE);
ResSortBreaks(&info->breakList, TRUE);
/* For long lists (defined as >= 16 entries), make a hash table of
* the node pointer conversions so that each node can be updated
* as we walk the list, instead of walking the rest of the list in
* a nested loop for each entry.
*/
if (count >= 16)
HashInit(&BreakTable, HT_DEFAULTSIZE, HT_CLIENTKEYS);
/*
* Eliminate breakpoints with the same X coordinate and merge
* their nodes.
*/
p2= info->breakList;
p2 = info->breakList;
/* Add extra left area to leftmost node */
p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile));
while (p2->br_next != NULL)
{
/* Has the node been recorded as needing to be replaced? */
if (count >= 16)
{
while (TRUE)
{
he = HashLookOnly(&BreakTable, (char *)p2->br_this);
if (!he) break;
p2->br_this = (resNode *)HashGetValue(he);
}
}
p1 = p2;
p2 = p2->br_next;
if (p2->br_loc.p_x == p1->br_loc.p_x)
@ -215,25 +234,38 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
/*
* Was the node used in another info or breakpoint?
* If so, replace the old node with the new one.
*
* Short lists: Walk the list to the end and change
* nodes on the fly.
* Long lists: Record the change to be made in the
* hash table so that it can be executed as each list
* entry is encountered.
*/
p3 = p2->br_next;
while (p3 != NULL)
if (count >= 16)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
p3 = p3->br_next;
he = HashFind(&BreakTable, (char *)currNode);
HashSetValue(he, (char *)p2->br_this);
}
}
else
{
p3 = p2->br_next;
while (p3 != NULL)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
/*
* If the X coordinates don't match, make a resistor between
* the breakpoints.
*/
p3 = p3->br_next;
}
}
}
else
{
/*
* If the X coordinates don't match, make a resistor between
* the breakpoints.
*/
else
{
resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor));
resistor->rr_nextResistor = (*resList);
resistor->rr_lastResistor = NULL;
@ -276,6 +308,8 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
}
}
if (count >= 16) HashKill(&BreakTable);
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
freeMagic((char *)p2);
info->breakList = NULL;
@ -301,7 +335,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
resNode **pendingList, **doneList;
resResistor **resList;
{
int width;
int count, width;
bool merged;
TileType ttype;
Breakpoint *p1, *p2, *p3;
@ -310,6 +344,8 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
resNode *currNode;
float rArea;
resInfo *info = (resInfo *)TiGetClientPTR(tile);
HashTable BreakTable;
HashEntry *he;
merged = FALSE;
width = RIGHT(tile) - LEFT(tile);
@ -329,7 +365,15 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
}
/* Re-sort nodes south to north. */
ResSortBreaks(&info->breakList, FALSE);
count = ResSortBreaks(&info->breakList, FALSE);
/* For long lists (defined as >= 16 entries), make a hash table of
* the node pointer conversions so that each node can be updated
* as we walk the list, instead of walking the rest of the list in
* a nested loop for each entry.
*/
if (count >= 16)
HashInit(&BreakTable, HT_DEFAULTSIZE, HT_CLIENTKEYS);
/* Simplified split tile handling */
if (IsSplit(tile))
@ -353,6 +397,16 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile));
while (p2->br_next != NULL)
{
/* Has the node been recorded as needing to be replaced? */
if (count >= 16)
{
while (TRUE)
{
he = HashLookOnly(&BreakTable, (char *)p2->br_this);
if (!he) break;
p2->br_this = (resNode *)HashGetValue(he);
}
}
p1 = p2;
p2 = p2->br_next;
if (p1->br_loc.p_y == p2->br_loc.p_y)
@ -390,14 +444,28 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
/*
* Was the node used in another info or breakpoint?
* If so, replace the old node with the new one.
*
* Short lists: Walk the list to the end and change
* nodes on the fly.
* Long lists: Record the change to be made in the
* hash table so that it can be executed as each list
* entry is encountered.
*/
p3 = p2->br_next;
while (p3 != NULL)
if (count >= 16)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
he = HashFind(&BreakTable, (char *)currNode);
HashSetValue(he, (char *)p2->br_this);
}
else
{
p3 = p2->br_next;
while (p3 != NULL)
{
if (p3->br_this == currNode)
p3->br_this = p2->br_this;
p3 = p3->br_next;
p3 = p3->br_next;
}
}
}
@ -1093,12 +1161,14 @@ MergeSortBreaks(Breakpoint *list, int xsort)
* bottleneck.
*
* Results:
* None
* Return the length of the list (maximum truncated at 16) so that
* the calling routine can determine if this is a long or a short
* linked list and treat it accordingly.
*
*-------------------------------------------------------------------------
*/
void
int
ResSortBreaks(masterlist, xsort)
Breakpoint **masterlist;
int xsort;
@ -1113,7 +1183,7 @@ ResSortBreaks(masterlist, xsort)
if (count > 16)
{
*masterlist = MergeSortBreaks(*masterlist, xsort);
return;
return count;
}
}
@ -1154,5 +1224,6 @@ ResSortBreaks(masterlist, xsort)
}
}
}
return count;
}

View File

@ -543,7 +543,7 @@ extern void ResCheckExtNodes();
extern void ResSortByGate();
extern void ResFixDevName();
extern void ResWriteLumpFile();
extern void ResSortBreaks();
extern int ResSortBreaks();
extern Plane *extResPrepSubstrate();
/* C99 compat */