Background
The following code (part of a natural language processor) was written to eliminate duplicate code by using isLeft
as a conditional throughout the method:
private void doInsideChartBinaryRules( boolean isLeft, int state, int start,
int end, int[] narrowLExtent_end,
int[] narrowRExtent_start,
int[] wideLExtent_end,
int[] wideRExtent_start,
float[] iScore_start_end,
float[][] iScore_start,
float[][][] iScore,
boolean lengthNormalization ) {
int narrowR = narrowRExtent_start[ state ],
narrowL = narrowLExtent_end[ state ];
BinaryRule[] rules =
( isLeft ) ?
bg.splitRulesWithLC( state ) :
bg.splitRulesWithRC( state );
for( BinaryRule rule : rules ) {
int leftChild = rule.leftChild;
int rightChild = rule.rightChild;
if( isLeft ) {
narrowL = narrowLExtent_end[ rightChild ];
// can this right constituent fit next to the left constituent?
if( narrowL < narrowR ) {
continue;
}
}
else {
narrowR = narrowRExtent_start[ leftChild ];
if( narrowR > narrowL ) {
continue;
}
}
int min2 =
( isLeft ) ? wideLExtent_end[ rightChild ] : wideLExtent_end[ state ];
int min = ( narrowR > min2 ? narrowR : min2 );
int max1 =
( isLeft ) ? wideRExtent_start[ state ] : wideRExtent_start[ leftChild ];
int max = ( max1 < narrowL ? max1 : narrowL );
if( min > max ) {
continue;
}
float pS = rule.score;
int parentState = rule.parent;
float oldIScore = iScore_start_end[ parentState ];
float bestIScore = oldIScore;
boolean foundBetter;
if( !lengthNormalization ) {
// find the split that can use this rule to make the max score
for( int split = min; split <= max; split++ ) {
boolean skip = false;
for( ParserConstraint c : constraints ) {
if( ( ( start < c.start && end >= c.end ) ||
( start <= c.start && end > c.end ) ) && split > c.start &&
split < c.end ) {
skip = true;
break;
}
if( ( start == c.start && split == c.end ) ) {
String tag =
isLeft ? stateIndex.get( state ) : stateIndex.get( leftChild );
Matcher m = c.state.matcher( tag );
if( !m.matches() ) {
skip = true;
break;
}
}
if( ( split == c.start && end == c.end ) ) {
String tag =
isLeft ? stateIndex.get( rightChild ) : stateIndex.get( state );
Matcher m = c.state.matcher( tag );
if( !m.matches() ) {
skip = true;
break;
}
}
}
if( skip ) {
continue;
}
float lS = ( isLeft ) ?
iScore_start[ split ][ state ] :
iScore_start[ split ][ leftChild ];
if( lS == Float.NEGATIVE_INFINITY ) {
continue;
}
float rS = ( isLeft ) ?
iScore[ split ][ end ][ rightChild ] :
iScore[ split ][ end ][ state ];
if( rS == Float.NEGATIVE_INFINITY ) {
continue;
}
float tot = pS + lS + rS;
if( tot > bestIScore ) {
bestIScore = tot;
}
}
foundBetter = bestIScore > oldIScore;
}
else {
int bestWordsInSpan = wordsInSpan[ start ][ end ][ parentState ];
float oldNormIScore = oldIScore / bestWordsInSpan;
float bestNormIScore = oldNormIScore;
for( int split = min; split <= max; split++ ) {
float lS = ( isLeft ) ?
iScore_start[ split ][ state ] :
iScore_start[ split ][ leftChild ];
if( lS == Float.NEGATIVE_INFINITY ) {
continue;
}
float rS = ( isLeft ) ?
iScore[ split ][ end ][ rightChild ] :
iScore[ split ][ end ][ state ];
if( rS == Float.NEGATIVE_INFINITY ) {
continue;
}
float tot = pS + lS + rS;
int newWordsInSpan = ( isLeft ) ?
wordsInSpan[ start ][ split ][ state ] +
wordsInSpan[ split ][ end ][ rightChild ] :
wordsInSpan[ start ][ split ][ leftChild ] +
wordsInSpan[ split ][ end ][ state ];
float normTot = tot / newWordsInSpan;
if( normTot > bestNormIScore ) {
bestIScore = tot;
bestNormIScore = normTot;
bestWordsInSpan = newWordsInSpan;
}
}
foundBetter = bestNormIScore > oldNormIScore;
if( foundBetter ) {
wordsInSpan[ start ][ end ][ parentState ] = bestWordsInSpan;
}
}
if( foundBetter ) {
iScore_start_end[ parentState ] = bestIScore;
if( oldIScore == Float.NEGATIVE_INFINITY ) {
if( start > narrowLExtent_end[ parentState ] ) {
narrowLExtent_end[ parentState ] = start;
wideLExtent_end[ parentState ] = start;
}
else {
if( start < wideLExtent_end[ parentState ] ) {
wideLExtent_end[ parentState ] = start;
}
}
if( end < narrowRExtent_start[ parentState ] ) {
narrowRExtent_start[ parentState ] = end;
wideRExtent_start[ parentState ] = end;
}
else {
if( end > wideRExtent_start[ parentState ] ) {
wideRExtent_start[ parentState ] = end;
}
}
}
}
}
}
Problem
This has caused a 10% performance decrease.
Question
How would you refactor the code to eliminate all the checks for isLeft
so as to regain (or exceed) the performance that was lost?
Thank you!
isLeft
flag. Besides that, you should use a profiler and provide a working example if expecting good answers. – tb- Mar 25 at 0:14