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:
parent
a062fdcfe0
commit
7a3717b02a
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Reference in New Issue