Skip to content

Commit

Permalink
Merge pull request #2444 from zspitzer/LDEV-5156-argument-local-scopes
Browse files Browse the repository at this point in the history
LDEV-5156 allow configuring the default capacity for local and arguments scopes
  • Loading branch information
zspitzer authored Dec 7, 2024
2 parents a3406a9 + 2e46a1e commit ea62cc8
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;
import java.util.Set;

import lucee.commons.io.SystemUtil;
import lucee.commons.lang.CFTypes;
import lucee.runtime.PageContext;
import lucee.runtime.config.NullSupportHelper;
Expand Down Expand Up @@ -63,14 +64,19 @@ public final class ArgumentImpl extends ScopeSupport implements Argument, ArrayP

private boolean bind;
private Set functionArgumentNames;
private static int argumentInitialCapacity;

static {
argumentInitialCapacity = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.scope.arguments.capacity", "16"), 16);
}
// private boolean supportFunctionArguments;

/**
* constructor of the class
*/
public ArgumentImpl() {
// super("arguments", SCOPE_ARGUMENTS, StructImpl.TYPE_LINKED, 4);
super("arguments", SCOPE_ARGUMENTS, StructImpl.TYPE_LINKED_NOT_SYNC, 4);
super("arguments", SCOPE_ARGUMENTS, StructImpl.TYPE_LINKED_NOT_SYNC, argumentInitialCapacity);
}

@Override
Expand Down
9 changes: 8 additions & 1 deletion core/src/main/java/lucee/runtime/type/scope/LocalImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,24 @@
**/
package lucee.runtime.type.scope;

import lucee.commons.io.SystemUtil;
import lucee.runtime.PageContext;
import lucee.runtime.op.Caster;
import lucee.runtime.type.Struct;

public final class LocalImpl extends ScopeSupport implements Scope, Local {

private static final long serialVersionUID = -7155406303949924403L;
private boolean bind;
private static int localInitialCapacity;

static {
localInitialCapacity = Caster.toIntValue(SystemUtil.getSystemPropOrEnvVar("lucee.scope.local.capacity", "16"), 16);
}

public LocalImpl() {
// super("local", Scope.SCOPE_LOCAL, Struct.TYPE_SYNC, 4);
super("local", Scope.SCOPE_LOCAL, Struct.TYPE_REGULAR, 4);
super("local", Scope.SCOPE_LOCAL, Struct.TYPE_REGULAR, localInitialCapacity);
}

@Override
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/resource/setting/sysprop-envvar.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,5 +378,13 @@
"sysprop": "lucee.dump.threads",
"envvar": "LUCEE_DUMP_THREADS",
"desc": "Used for debugging, when enabled, it will dump out running threads to the console via the background controller thread"
"sysprop": "lucee.scope.local.capacity",
"envvar": "LUCEE_SCOPE_LOCAL_CAPACITY",
"desc": "Sets the initial capacity (size) for the local scope hashmap"
},
{
"sysprop": "lucee.scope.arguments.capacity",
"envvar": "LUCEE_SCOPE_ARGUMENTS_CAPACITY",
"desc": "Sets the initial capacity (size) for the arguments scope hashmap"
}
]
105 changes: 105 additions & 0 deletions test/tickets/LDEV5156.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
component extends = "org.lucee.cfml.test.LuceeTestCase" skip="true" {

/*
run with
-DtestFilter="5156" -DUseEpsilonGC="true"
so it runs alone and without any GC for better memory info
*/

function testStructSize() localmode=true {
rounds = 25000;
TYPE_LINKED_NOT_SYNC = 100; //args
TYPE_REGULAR = 3; // local
systemOutput(" ", true);
_testStructSize(fill=0, rounds=rounds);
systemOutput(" ---warm up complete--- ", true);
systemOutput(" --- test TYPE_REGULAR / local scope --- ", true);
_testStructSize(fill=0, rounds=rounds, structType=TYPE_REGULAR);
_testStructSize(fill=2, rounds=rounds, structType=TYPE_REGULAR);
_testStructSize(fill=4, rounds=rounds, structType=TYPE_REGULAR);
_testStructSize(fill=8, rounds=rounds, structType=TYPE_REGULAR);

systemOutput(" --- test TYPE_LINKED_NOT_SYNC / arguments scope --- ", true);
_testStructSize(fill=0, rounds=rounds, structType=TYPE_LINKED_NOT_SYNC);
_testStructSize(fill=2, rounds=rounds, structType=TYPE_LINKED_NOT_SYNC);
_testStructSize(fill=4, rounds=rounds, structType=TYPE_LINKED_NOT_SYNC);
_testStructSize(fill=8, rounds=rounds, structType=TYPE_LINKED_NOT_SYNC);
}

private function _testStructSize(fill, rounds, structType) localmode=true {
loop list="4,8,16,32" item="initialCapacity"{
//createObject( "java", "java.lang.System" ).gc();
//systemOutput(" ", true);
//systemOutput("testing initialCapacity: #initialCapacity#, fill: #arguments.fill# ", true);
s = getTickCount();
start = reportMem( "", {}, "start" );
a=[];
while(true){
st = createObject("java","lucee.runtime.type.StructImpl").init(int(arguments.structType), initialCapacity);
for ( i=1; i < arguments.fill ; i++ )
st["fill#i#"]=1; // populating the struct, potentially beyond fill factor, triggering a resize
for ( i=1; i < arguments.fill ; i++ )
st["fill#i#"]=2; // also test accessing the struct
arrayAppend(a, st);
/*
if (arrayLen(a) mod 5000 eq 0){
systemOutput(a.len() & " ");
// echo(a.len() & ", ");
flush;
}
*/
if (len(a) == rounds) break;
}
//systemOutput(" ", true);
if (initialCapacity < 10) initialCapacity = " #initialCapacity#"; //
systemOutput("initialCapacity: #initialCapacity#, fill: #arguments.fill#, rounds: #numberformat(rounds)#, took #numberformat(getTickCount()-s)# ms, ");
r = reportMem( "", start.usage, "st" );
for (rr in r.report){
if (rr contains "G1" || rr contains "Epsilon")
systemOutput(rr, true);
}
//systemOutput(r.report, true);

//dump(getTickCount()-s & "ms");
//dump(url.size);
//dump(r.report);
//systemOutput(" ", true);
}

systemOutput("----", true);

}

private function reportMem ( string type, struct prev={}, string name="" ) {
var qry = getMemoryUsage( type );
var report = [];
var used = { name: arguments.name };
querySort(qry,"type,name");
loop query=qry {
if (qry.max == -1)
var perc = 0;
else
var perc = int( ( qry.used / qry.max ) * 100 );
//if(qry.max<0 || qry.used<0 || perc<90) continue;
//if(qry.max<0 || qry.used<0 || perc<90) continue;
var rpt = replace(ucFirst(qry.type), '_', ' ')
& " " & qry.name & ": " & numberFormat(perc) & "%, " & numberFormat( qry.used / 1024 / 1024 ) & " Mb";
if ( structKeyExists( arguments.prev, qry.name ) ) {
var change = numberFormat( (qry.used - arguments.prev[ qry.name ] ) / 1024 / 1024 );
if ( change gt 0 ) {
rpt &= ", (+ " & change & "Mb )";
} else if ( change lt 0 ) {
rpt &= ", ( " & change & "Mb )";
}
}
arrayAppend( report, rpt );
used[ qry.name ] = qry.used;
}
return {
report: report,
usage: used
};
}
}

0 comments on commit ea62cc8

Please sign in to comment.