Replaced localContextStack with specialized ArrayList-like class for some speed gain
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/325bbd08 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/325bbd08 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/325bbd08 Branch: refs/heads/master Commit: 325bbd088a841725014da68078cda76258f2c9df Parents: 079b701 Author: ddekany <ddek...@apache.org> Authored: Sun Dec 6 01:45:52 2015 +0100 Committer: ddekany <ddek...@apache.org> Committed: Sun Dec 6 01:45:52 2015 +0100 ---------------------------------------------------------------------- src/main/java/freemarker/core/Environment.java | 26 ++++++------- .../java/freemarker/core/IteratorBlock.java | 2 +- .../java/freemarker/core/LocalContextStack.java | 39 ++++++++++++++++++++ src/main/java/freemarker/core/Macro.java | 5 +-- 4 files changed, 53 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/325bbd08/src/main/java/freemarker/core/Environment.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java index 08c10d0..dcc178a 100644 --- a/src/main/java/freemarker/core/Environment.java +++ b/src/main/java/freemarker/core/Environment.java @@ -159,7 +159,7 @@ public final class Environment extends Configurable { private Writer out; private Macro.Context currentMacroContext; - private ArrayList localContextStack; + private LocalContextStack localContextStack; private final Namespace mainNamespace; private Namespace currentNamespace, globalNamespace; private HashMap loadedLibs; @@ -377,7 +377,7 @@ public final class Environment extends Configurable { directiveModel.execute(this, args, outArgs, nested); } finally { if (outArgs.length > 0) { - popLocalContext(); + localContextStack.pop(); } } } @@ -500,7 +500,7 @@ public final class Environment extends Configurable { */ void invokeNestedContent(BodyInstruction.Context bodyCtx) throws TemplateException, IOException { Macro.Context invokingMacroContext = getCurrentMacroContext(); - ArrayList prevLocalContextStack = localContextStack; + LocalContextStack prevLocalContextStack = localContextStack; TemplateElement nestedContent = invokingMacroContext.nestedContent; if (nestedContent != null) { this.currentMacroContext = invokingMacroContext.prevMacroContext; @@ -523,7 +523,7 @@ public final class Environment extends Configurable { visit(nestedContent); } finally { if (invokingMacroContext.nestedContentParameterNames != null) { - popLocalContext(); + localContextStack.pop(); } this.currentMacroContext = invokingMacroContext; currentNamespace = getMacroNamespace(invokingMacroContext.getMacro()); @@ -549,7 +549,7 @@ public final class Environment extends Configurable { handleTemplateException(te); return true; } finally { - popLocalContext(); + localContextStack.pop(); } } @@ -655,7 +655,7 @@ public final class Environment extends Configurable { final Macro.Context prevMacroCtx = currentMacroContext; currentMacroContext = macroCtx; - final ArrayList prevLocalContextStack = localContextStack; + final LocalContextStack prevLocalContextStack = localContextStack; localContextStack = null; final Namespace prevNamespace = currentNamespace; @@ -1813,7 +1813,7 @@ public final class Environment extends Configurable { public TemplateModel getLocalVariable(String name) throws TemplateModelException { if (localContextStack != null) { for (int i = localContextStack.size() - 1; i >= 0; i--) { - LocalContext lc = (LocalContext) localContextStack.get(i); + LocalContext lc = localContextStack.get(i); TemplateModel tm = lc.getLocalVariable(name); if (tm != null) { return tm; @@ -1940,7 +1940,7 @@ public final class Environment extends Configurable { } if (localContextStack != null) { for (int i = localContextStack.size() - 1; i >= 0; i--) { - LocalContext lc = (LocalContext) localContextStack.get(i); + LocalContext lc = localContextStack.get(i); set.addAll(lc.getLocalVariableNames()); } } @@ -2101,16 +2101,12 @@ public final class Environment extends Configurable { private void pushLocalContext(LocalContext localContext) { if (localContextStack == null) { - localContextStack = new ArrayList(); + localContextStack = new LocalContextStack(); } - localContextStack.add(localContext); + localContextStack.push(localContext); } - private void popLocalContext() { - localContextStack.remove(localContextStack.size() - 1); - } - - ArrayList getLocalContextStack() { + LocalContextStack getLocalContextStack() { return localContextStack; } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/325bbd08/src/main/java/freemarker/core/IteratorBlock.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/IteratorBlock.java b/src/main/java/freemarker/core/IteratorBlock.java index e6c760b..62c6e34 100644 --- a/src/main/java/freemarker/core/IteratorBlock.java +++ b/src/main/java/freemarker/core/IteratorBlock.java @@ -89,7 +89,7 @@ final class IteratorBlock extends TemplateElement { */ static IterationContext findEnclosingIterationContext(Environment env, String loopVariableName) throws _MiscTemplateException { - ArrayList ctxStack = env.getLocalContextStack(); + LocalContextStack ctxStack = env.getLocalContextStack(); if (ctxStack != null) { for (int i = ctxStack.size() - 1; i >= 0; i--) { Object ctx = ctxStack.get(i); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/325bbd08/src/main/java/freemarker/core/LocalContextStack.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/LocalContextStack.java b/src/main/java/freemarker/core/LocalContextStack.java new file mode 100644 index 0000000..5f556bf --- /dev/null +++ b/src/main/java/freemarker/core/LocalContextStack.java @@ -0,0 +1,39 @@ +package freemarker.core; + +/** + * Class that's a little bit more efficient than using an {@code ArrayList<LocalContext>}. + * + * @since 2.3.24 + */ +final class LocalContextStack { + + private LocalContext[] buffer = new LocalContext[8]; + private int size; + + void push(LocalContext localContext) { + final int newSize = ++size; + LocalContext[] buffer = this.buffer; + if (buffer.length < newSize) { + final LocalContext[] newBuffer = new LocalContext[newSize * 2]; + for (int i = 0; i < buffer.length; i++) { + newBuffer[i] = buffer[i]; + } + buffer = newBuffer; + this.buffer = newBuffer; + } + buffer[newSize - 1] = localContext; + } + + void pop() { + buffer[--size] = null; + } + + public LocalContext get(int index) { + return buffer[index]; + } + + public int size() { + return size; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/325bbd08/src/main/java/freemarker/core/Macro.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/Macro.java b/src/main/java/freemarker/core/Macro.java index 5310947..d639d4f 100644 --- a/src/main/java/freemarker/core/Macro.java +++ b/src/main/java/freemarker/core/Macro.java @@ -20,7 +20,6 @@ package freemarker.core; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -160,13 +159,13 @@ public final class Macro extends TemplateElement implements TemplateModel { final TemplateElement nestedContent; final Environment.Namespace nestedContentNamespace; final List nestedContentParameterNames; - final ArrayList prevLocalContextStack; + final LocalContextStack prevLocalContextStack; final Context prevMacroContext; Context(Environment env, TemplateElement nestedContent, List nestedContentParameterNames) { - this.localVars = env.new Namespace(); + this.localVars = env.new Namespace(); this.nestedContent = nestedContent; this.nestedContentNamespace = env.getCurrentNamespace(); this.nestedContentParameterNames = nestedContentParameterNames;