Bug 16773

Summary: Use of new Boolean() has performance implications
Product: Taglibs Reporter: Heath Chiavettone <hchiavettone>
Component: Standard TaglibAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: enhancement    
Priority: P3    
Version: 1.0   
Target Milestone: ---   
Hardware: All   
OS: other   

Description Heath Chiavettone 2003-02-04 19:00:31 UTC
In looking through the JSTL source, I noticed 40 occurances (listed below) 
where the code was creating new Boolean objects.  In a system where 
performance is critical, this creation of garbage Boolean objects can increase 
the overall memory load of a system.  It is much preferable to use the 
Boolean.TRUE and Boolean.FALSE static values in situations where the use of a 
Boolean is required.  It is fairly easy to write a simple public static final 
helper method (getBoolean(boolean flag)) that does a {if (flag) return 
Boolean.TRUE; return Boolean.FALSE;}

Thanks for you help in improving JSTL's performance.

Heath Chiavettone

 \jakarta-
taglibs\standard\src\javax\servlet\jsp\jstl\core\ConditionalTagSupport.java
(185,43):            pageContext.setAttribute(var, new Boolean(result), scope);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\extra\spath\SPathParser.java
(460,27):    boolean[] la1tokens = new boolean[20];
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(129,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(155,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(157,25):            converted = new Boolean(true);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(159,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(167,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(169,25):            converted = new Boolean(true);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(171,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(185,25):            converted = new Boolean(false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\adapter\Convert.jav
a(192,25):            converted = new Boolean(true);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\AndOpera
tor.java(201,22):            result = new Boolean(leftSide && rightSide);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\BooleanL
iteral.java(185,16):        return new Boolean(val);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Contains
Function.java(218,22):            result = new Boolean(arg1.indexOf(arg2) != -
1);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\EqualsOp
erator.java(237,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\GreaterT
hanEqualOperator.java(238,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\GreaterT
hanOperator.java(238,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\LessThan
EqualOperator.java(238,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\LessThan
Operator.java(238,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\NotEqual
sOperator.java(237,16):        return new Boolean(result);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\NotFunct
ion.java(198,16):        return new Boolean(result.booleanValue() == false);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\OrOperat
or.java(201,22):            result = new Boolean(leftSide || rightSide);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j
ava(885,54):                           BooleanFunction jjtn001 = new 
BooleanFunction(JJTBOOLEANFUNCTION);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j
ava(1808,29):   BooleanLiteral jjtn001 = new BooleanLiteral(JJTBOOLEANLITERAL);
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\Parser.j
ava(2679,27):    boolean[] la1tokens = new boolean[65];
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jpath\expression\StartsWi
thFunction.java(218,22):            result = new Boolean(arg1.startsWith
(arg2));
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\BooleanLiteral.java
(73,45):  public static final BooleanLiteral TRUE = new BooleanLiteral 
("true");
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\BooleanLiteral.java
(74,46):  public static final BooleanLiteral FALSE = new BooleanLiteral 
("false");
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\parser\ELParser.java
(1093,27):    boolean[] la1tokens = new boolean[54];
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\lang\jstl\parser\jsp20
\ELParser.java(1090,27):    boolean[] la1tokens = new boolean[54];
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\tag\common\core\ForEachSupport
.java(296,29):        Boolean[] wrapped = new Boolean[a.length];
\jakarta-
taglibs\standard\src\org\apache\taglibs\standard\tag\common\core\ForEachSupport
.java(298,26):            wrapped[i] = new Boolean(a[i]);
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java
(206,26):		    chooseHasWhen.push(new Boolean(true));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java
(222,31):		    chooseHasOtherwise.push(new Boolean(true));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java
(251,22):		chooseHasWhen.push(new Boolean(false));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlCoreTLV.java
(252,27):		chooseHasOtherwise.push(new Boolean(false));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java
(201,40):                    chooseHasWhen.push(new Boolean(true));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java
(217,31):		    chooseHasOtherwise.push(new Boolean(true));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java
(239,36):                chooseHasWhen.push(new Boolean(false));
\jakarta-taglibs\standard\src\org\apache\taglibs\standard\tlv\JstlXmlTLV.java
(240,27):		chooseHasOtherwise.push(new Boolean(false));
Comment 1 Shawn Bayern 2003-02-04 19:11:19 UTC
Do you have some evidence that this leads, in practice, to a performance-
problem on any real-world system.  The change you're suggesting is minor, so I 
can just make it as soon as I get a chance, but I'm not inclined to go out of 
my way to intuit things about system performance without hard evidence.  My 
impression is that any legitimate JIT knows how to optimize this kind of code; 
object creation is emphatically *not* expensive on nearly all real-world JITs, 
and code is often made complex out of a mistaken desire to avoid it!
Comment 2 Felipe Leme 2003-08-19 00:39:54 UTC
I agree with Shawn the JITs should take care of these kinds of optimization. In
fact, if they do, then your approach would penalize the performance, as it would
require an extra method call.

On the other hand, such static function already exists in JDK 1.4.2: 

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Boolean.html#valueOf(boolean)

The fact that this function exists suggests that creating new Booleans in fact a
decreases performance. If JSTL depended on JDK 1.4.2, we could easily fix this
by using replacing the occurrences of "new Boolean(x)" to "Boolean.valueOf(x)",
but unfortunately that's not the case. Another option would be
Boolean.valueOf(""+x), as JDK 1.3.x has a valueOf(String) method.

Just my 2 cents,

Felipe



Comment 3 Justyna Horwat 2004-05-11 23:23:54 UTC
Did a general audit and substituted static values where Boolean objects were created where 
appropriate. Changes were made to standard HEAD and available in the nightly build and will be 
available in the upcoming Standard 1.1.1 release.

I agree with Shawn and Felipe's assessment that the JIT should take care of this type of optimization so 
therefore the static helper method won't be implemented. I believe that the added method call may 
penalize performance.