Created
June 24, 2022 11:30
-
-
Save bennadel/619a8811f50ff981a8460b566e6ccde8 to your computer and use it in GitHub Desktop.
Looking At The Performance Overhead Of A Read-Only Lock In Lucee CFML 5.3.8.201
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
coreCount = createObject( "java", "java.lang.Runtime" ) | |
.getRuntime() | |
.availableProcessors() | |
; | |
dump( coreCount ); | |
</cfscript> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
With-lock test | |
Loop Counter: 5263 | |
Value Counter: 10491977 | |
With-lock test | |
Loop Counter: 4939 | |
Value Counter: 9835909 | |
With-lock test | |
Loop Counter: 5045 | |
Value Counter: 10060834 | |
With-lock test | |
Loop Counter: 5358 | |
Value Counter: 10688017 | |
With-lock test | |
Loop Counter: 5642 | |
Value Counter: 11256738 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
// Let's attempt to simulate concurrent request activity all trying to access shared | |
// data. Each entry in the simulated request will be executed via parallel iteration. | |
// And, each parallel iteration will try to iterate over the given shared data array. | |
simulatedRequests = buildArray( 20 ); | |
sharedData = buildArray( 100 ); | |
// Let's keep track of how many test iterations we perform in our test window. | |
loopCounter = 0; | |
valueCounter = 0; | |
// Each test window will be 10-seconds long. | |
cutoffAt = ( getTickCount() + ( 10 * 1000 ) ); | |
// Let's see how many contentious read operations we can perform in our test window. | |
while ( getTickCount() < cutoffAt ) { | |
simulatedRequests.each( | |
() => { | |
lock | |
name = "read-only-lock-test" | |
type = "readonly" | |
timeout = 5 | |
{ | |
for ( var increment in sharedData ) { | |
// CAUTION: The "++" operator is NOT THREAD SAFE. As such, we | |
// cannot trust the following operation inside a parallel | |
// iterator. That said, I have it here in order to make sure that | |
// the Lucee compiler doesn't try to optimize this inner loop | |
// away. I wanted to make sure that we're consuming the iteration | |
// value in some way. | |
valueCounter += increment; | |
} | |
} | |
}, | |
// Run the .each() in parallel using Java's thread pool. | |
true, | |
// Maximum number of parallel threads. | |
simulatedRequests.len() | |
); | |
loopCounter++; | |
}; | |
echo( "With-lock test <br />" ); | |
echo( "Loop Counter: #loopCounter.intValue()# <br />" ); | |
echo( "Value Counter: #valueCounter.intValue()# <br />" ); | |
// ------------------------------------------------------------------------------- // | |
// ------------------------------------------------------------------------------- // | |
/** | |
* I construct an array of the given size in each value is "1". | |
*/ | |
public array function buildArray( required numeric size ) { | |
var result = []; | |
for ( var i = 1 ; i <= size ; i++ ) { | |
result[ i ] = 1; // All values are 1 (for our counter). | |
} | |
return( result ); | |
} | |
</cfscript> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Without-lock test | |
Loop Counter: 5397 | |
Value Counter: 10769762 | |
Without-lock test | |
Loop Counter: 4964 | |
Value Counter: 9895341 | |
Without-lock test | |
Loop Counter: 5138 | |
Value Counter: 10242939 | |
Without-lock test | |
Loop Counter: 5296 | |
Value Counter: 10552607 | |
Without-lock test | |
Loop Counter: 4885 | |
Value Counter: 9740710 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<cfscript> | |
// Let's attempt to simulate concurrent request activity all trying to access shared | |
// data. Each entry in the simulated request will be executed via parallel iteration. | |
// And, each parallel iteration will try to iterate over the given shared data array. | |
simulatedRequests = buildArray( 20 ); | |
sharedData = buildArray( 100 ); | |
// Let's keep track of how many test iterations we perform in our test window. | |
loopCounter = 0; | |
valueCounter = 0; | |
// Each test window will be 10-seconds long. | |
cutoffAt = ( getTickCount() + ( 10 * 1000 ) ); | |
// Let's see how many contentious read operations we can perform in our test window. | |
while ( getTickCount() < cutoffAt ) { | |
simulatedRequests.each( | |
() => { | |
for ( var increment in sharedData ) { | |
// CAUTION: The "++" operator is NOT THREAD SAFE. As such, we cannot | |
// trust the following operation inside a parallel iterator. That | |
// said, I have it here in order to make sure that the Lucee compiler | |
// doesn't try to optimize this inner loop away. I wanted to make sure | |
// that we're consuming the iteration value in some way. | |
valueCounter += increment; | |
} | |
}, | |
// Run the .each() in parallel using Java's thread pool. | |
true, | |
// Maximum number of parallel threads. | |
simulatedRequests.len() | |
); | |
loopCounter++; | |
} | |
echo( "Without-lock test <br />" ); | |
echo( "Loop Counter: #loopCounter# <br />" ); | |
echo( "Value Counter: #valueCounter.intValue()# <br />" ); | |
// ------------------------------------------------------------------------------- // | |
// ------------------------------------------------------------------------------- // | |
/** | |
* I construct an array of the given size in each value is "1". | |
*/ | |
public array function buildArray( required numeric size ) { | |
var result = []; | |
for ( var i = 1 ; i <= size ; i++ ) { | |
result[ i ] = 1; // All values are 1 (for our counter). | |
} | |
return( result ); | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment