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
79e2dbdd43
|
|
@ -125,7 +125,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
resNode **pendingList, **doneList;
|
resNode **pendingList, **doneList;
|
||||||
resResistor **resList;
|
resResistor **resList;
|
||||||
{
|
{
|
||||||
int height;
|
int count, height;
|
||||||
bool merged;
|
bool merged;
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
Breakpoint *p1, *p2, *p3;
|
Breakpoint *p1, *p2, *p3;
|
||||||
|
|
@ -134,6 +134,8 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
resNode *currNode;
|
resNode *currNode;
|
||||||
float rArea;
|
float rArea;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
||||||
|
HashTable BreakTable;
|
||||||
|
HashEntry *he;
|
||||||
|
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
height = TOP(tile) - BOTTOM(tile);
|
height = TOP(tile) - BOTTOM(tile);
|
||||||
|
|
@ -163,21 +165,38 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
ttype = TiGetTypeExact(tile);
|
ttype = TiGetTypeExact(tile);
|
||||||
|
|
||||||
/* Re-sort nodes left to right. */
|
/* 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
|
* Eliminate breakpoints with the same X coordinate and merge
|
||||||
* their nodes.
|
* their nodes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p2= info->breakList;
|
p2 = info->breakList;
|
||||||
|
|
||||||
/* Add extra left area to leftmost node */
|
/* Add extra left area to leftmost node */
|
||||||
|
|
||||||
p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile));
|
p2->br_this->rn_float.rn_area += height * (p2->br_loc.p_x - LEFT(tile));
|
||||||
while (p2->br_next != NULL)
|
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;
|
p1 = p2;
|
||||||
p2 = p2->br_next;
|
p2 = p2->br_next;
|
||||||
if (p2->br_loc.p_x == p1->br_loc.p_x)
|
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?
|
* Was the node used in another info or breakpoint?
|
||||||
* If so, replace the old node with the new one.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
if (count >= 16)
|
||||||
p3 = p2->br_next;
|
|
||||||
while (p3 != NULL)
|
|
||||||
{
|
{
|
||||||
if (p3->br_this == currNode)
|
he = HashFind(&BreakTable, (char *)currNode);
|
||||||
p3->br_this = p2->br_this;
|
HashSetValue(he, (char *)p2->br_this);
|
||||||
|
|
||||||
p3 = p3->br_next;
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
p3 = p2->br_next;
|
||||||
|
while (p3 != NULL)
|
||||||
|
{
|
||||||
|
if (p3->br_this == currNode)
|
||||||
|
p3->br_this = p2->br_this;
|
||||||
|
|
||||||
/*
|
p3 = p3->br_next;
|
||||||
* If the X coordinates don't match, make a resistor between
|
}
|
||||||
* the breakpoints.
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
else
|
/*
|
||||||
{
|
* If the X coordinates don't match, make a resistor between
|
||||||
|
* the breakpoints.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor));
|
resistor = (resResistor *)mallocMagic((unsigned)sizeof(resResistor));
|
||||||
resistor->rr_nextResistor = (*resList);
|
resistor->rr_nextResistor = (*resList);
|
||||||
resistor->rr_lastResistor = NULL;
|
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);
|
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
|
||||||
freeMagic((char *)p2);
|
freeMagic((char *)p2);
|
||||||
info->breakList = NULL;
|
info->breakList = NULL;
|
||||||
|
|
@ -301,7 +335,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
resNode **pendingList, **doneList;
|
resNode **pendingList, **doneList;
|
||||||
resResistor **resList;
|
resResistor **resList;
|
||||||
{
|
{
|
||||||
int width;
|
int count, width;
|
||||||
bool merged;
|
bool merged;
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
Breakpoint *p1, *p2, *p3;
|
Breakpoint *p1, *p2, *p3;
|
||||||
|
|
@ -310,6 +344,8 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
resNode *currNode;
|
resNode *currNode;
|
||||||
float rArea;
|
float rArea;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
||||||
|
HashTable BreakTable;
|
||||||
|
HashEntry *he;
|
||||||
|
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
width = RIGHT(tile) - LEFT(tile);
|
width = RIGHT(tile) - LEFT(tile);
|
||||||
|
|
@ -329,7 +365,15 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-sort nodes south to north. */
|
/* 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 */
|
/* Simplified split tile handling */
|
||||||
if (IsSplit(tile))
|
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));
|
p2->br_this->rn_float.rn_area += width * (p2->br_loc.p_y - BOTTOM(tile));
|
||||||
while (p2->br_next != NULL)
|
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;
|
p1 = p2;
|
||||||
p2 = p2->br_next;
|
p2 = p2->br_next;
|
||||||
if (p1->br_loc.p_y == p2->br_loc.p_y)
|
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?
|
* Was the node used in another info or breakpoint?
|
||||||
* If so, replace the old node with the new one.
|
* 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;
|
if (count >= 16)
|
||||||
while (p3 != NULL)
|
|
||||||
{
|
{
|
||||||
if (p3->br_this == currNode)
|
he = HashFind(&BreakTable, (char *)currNode);
|
||||||
p3->br_this = p2->br_this;
|
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.
|
* bottleneck.
|
||||||
*
|
*
|
||||||
* Results:
|
* 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)
|
ResSortBreaks(masterlist, xsort)
|
||||||
Breakpoint **masterlist;
|
Breakpoint **masterlist;
|
||||||
int xsort;
|
int xsort;
|
||||||
|
|
@ -1113,7 +1183,7 @@ ResSortBreaks(masterlist, xsort)
|
||||||
if (count > 16)
|
if (count > 16)
|
||||||
{
|
{
|
||||||
*masterlist = MergeSortBreaks(*masterlist, xsort);
|
*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 ResSortByGate();
|
||||||
extern void ResFixDevName();
|
extern void ResFixDevName();
|
||||||
extern void ResWriteLumpFile();
|
extern void ResWriteLumpFile();
|
||||||
extern void ResSortBreaks();
|
extern int ResSortBreaks();
|
||||||
extern Plane *extResPrepSubstrate();
|
extern Plane *extResPrepSubstrate();
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue