In FanInt.java, the isSpace, isAlpha and isAlphaNum methods use a try..catch block to optimize for a rare case. But, isn't just setting up the exception handler a higher performance penalty than the corresponding integer comparison in the existing if statement?
brianFri 5 Jun 2009
I don't think so - I don't think adding a try block has any overhead unless an exception is actually thrown. But I'm not sure, I guess we could try to gather some empirical evidence.
qualidafialFri 5 Jun 2009
I've run a benchmark with the following code:
public void testIsSpace_TryCatch() {
runBenchmark( "isSpace_TryCatch", new Runnable() {
int count;
public void run() {
for ( int i = 0; i < Integer.MAX_VALUE; i++ )
if ( isSpace_TryCatch( i & 0x7F ) )
count++;
}
} );
}
public static boolean isSpace_TryCatch( long self ) {
try {
return ( self < 128 && ( charMap[(int) self] & SPACE ) != 0 );
}
catch ( ArrayIndexOutOfBoundsException e ) {
// should be very rare to use this method with negative
// numbers, so don't take the hit every call
return false;
}
}
public void testIsSpace_IfClause() {
runBenchmark( "isSpace_IntCompare", new Runnable() {
int count;
public void run() {
for ( int i = 0; i < Integer.MAX_VALUE; i++ )
if ( isSpace_IntCompare( i & 0x7F ) )
count++;
}
} );
}
public static boolean isSpace_IntCompare( long self ) {
return ( self < 128 && self >= 0 && ( charMap[(int) self] & SPACE ) != 0 );
}
Note that the int count stuff had to be added to keep the VM from optimizing away the isSpace method calls.
The results:
Benchmarking 'isSpace_TryCatch':
Run 1/10: 3577ms
Run 2/10: 3521ms
Run 3/10: 3526ms
Run 4/10: 3494ms
Run 5/10: 3498ms
Run 6/10: 3505ms
Run 7/10: 3495ms
Run 8/10: 3499ms
Run 9/10: 3498ms
Run 10/10: 3501ms
Total: 35114ms
Average: 3,511.4ms
Benchmarking 'isSpace_IntCompare':
Run 1/10: 3510ms
Run 2/10: 3537ms
Run 3/10: 3507ms
Run 4/10: 3508ms
Run 5/10: 3523ms
Run 6/10: 3524ms
Run 7/10: 3533ms
Run 8/10: 3501ms
Run 9/10: 3505ms
Run 10/10: 3500ms
Total: 35148ms
Average: 3,514.8ms
So it appears that while my previous concern about try/catch affecting performance is moot, so is the stated reasoning for using a try/catch block in the first place. It just doesn't make a difference either way.
The benchmark utility I use is a home-grown one which I'm happy to share if you're curious or if you want to reproduce these results on your machine.
qualidafialFri 5 Jun 2009
I ran the benchmark again, this time using java -Xint to eliminate VM optimizations. I had to modify the test to make it run in a reasonable time:
private static int COUNT = 1 << 24;
public void testIsSpace_TryCatch() {
runBenchmark( "isSpace_TryCatch", new Runnable() {
public void run() {
for ( int i = 0; i < COUNT; i++ )
isSpace_TryCatch( 17 );
}
} );
}
public static boolean isSpace_TryCatch( long self ) {
// same as before
}
public void testIsSpace_IfClause() {
runBenchmark( "isSpace_IntCompare", new Runnable() {
public void run() {
for ( int i = 0; i < COUNT; i++ )
isSpace_IntCompare( 17 );
}
} );
}
public static boolean isSpace_IntCompare( long self ) {
// same as before
}
Results:
Benchmarking 'isSpace_TryCatch':
Run 1/10: 1743ms
Run 2/10: 1732ms
Run 3/10: 1749ms
Run 4/10: 1746ms
Run 5/10: 1738ms
Run 6/10: 1734ms
Run 7/10: 1734ms
Run 8/10: 1750ms
Run 9/10: 1750ms
Run 10/10: 1740ms
Total: 17416ms
Average: 1,741.6ms
Benchmarking 'isSpace_IntCompare':
Run 1/10: 1831ms
Run 2/10: 1824ms
Run 3/10: 1828ms
Run 4/10: 1828ms
Run 5/10: 1826ms
Run 6/10: 1827ms
Run 7/10: 1828ms
Run 8/10: 1828ms
Run 9/10: 1827ms
Run 10/10: 1829ms
Total: 18276ms
Average: 1,827.6ms
So the int comparison actually does take about 5% longer compared to using a try / catch block, in interpreted mode.
qualidafial Fri 5 Jun 2009
In FanInt.java, the
isSpace
,isAlpha
andisAlphaNum
methods use atry..catch
block to optimize for a rare case. But, isn't just setting up the exception handler a higher performance penalty than the corresponding integer comparison in the existing if statement?brian Fri 5 Jun 2009
I don't think so - I don't think adding a try block has any overhead unless an exception is actually thrown. But I'm not sure, I guess we could try to gather some empirical evidence.
qualidafial Fri 5 Jun 2009
I've run a benchmark with the following code:
Note that the
int count
stuff had to be added to keep the VM from optimizing away theisSpace
method calls.The results:
So it appears that while my previous concern about try/catch affecting performance is moot, so is the stated reasoning for using a try/catch block in the first place. It just doesn't make a difference either way.
The benchmark utility I use is a home-grown one which I'm happy to share if you're curious or if you want to reproduce these results on your machine.
qualidafial Fri 5 Jun 2009
I ran the benchmark again, this time using
java -Xint
to eliminate VM optimizations. I had to modify the test to make it run in a reasonable time:Results:
So the int comparison actually does take about 5% longer compared to using a try / catch block, in interpreted mode.
brian Sat 6 Jun 2009
Interesting. Thanks for running those benchmarks.