I just find in an experence share presentation from infoq. It claims that if you convert the String to byte[] in servlet, it will increase the QPS (Queries per Second?). The code example shows the comparison:
Before
private static String content = “…94k…”;
protected doGet(…){
response.getWrite().print(content);
}
After
private static String content = “…94k…”;
Private static byte[] bytes = content.getBytes();
protected doGet(…){
response.getOutputStream().write(bytes);
}
Result before
- page size(K)94
- max QPS 1800
Result after
- page size(K)94
- max QPS 3500
Can anyone explain why it was optimized? I trust it to be true.
UPDATE
In case I cause any misleading. I need explain that the original presentation only uses this as an example. They actually refactor the velocity engine by this way. BUt this source code is a bit long.
Actually in the presentation didn't imply how they do it in detail. But I found some lead.
In ASTText.java, they cached the byte[] ctext instead of char[] ctext , which boosts the performance a lot~!
Just like the way above. It makes a lot of sense,right?
(BUT definitely they should also refactor the Node interface. Writer cannot write byte[]. Which means using OutputStream instead!)
As Perception adviced actually a Write finally delegate to a StreamEncoder. And StreamEncoder write will first change char[] into byte[]. And then delegate it to the OutputSteam to do the real write. You can easily refer to the source code and prove it. Considering render method will be called each time for showing the page, the saving of cost will be considerable.
StreamEncoder.class
public class ASTText extends SimpleNode {
private char[] ctext;
/**
* @param id
*/
public ASTText(int id) {
super (id);
}
/**
* @param p
* @param id
*/
public ASTText(Parser p, int id) {
super (p, id);
}
/**
* @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
*/
public Object jjtAccept(ParserVisitor visitor, Object data) {
return visitor.visit(this , data);
}
/**
* @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
*/
public Object init(InternalContextAdapter context, Object data)
throws TemplateInitException {
Token t = getFirstToken();
String text = NodeUtils.tokenLiteral(t);
ctext = text.toCharArray();
return data;
}
/**
* @see org.apache.velocity.runtime.parser.node.SimpleNode#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer)
*/
public boolean render(InternalContextAdapter context, Writer writer)
throws IOException {
if (context.getAllowRendering()) {
writer.write(ctext);
}
return true;
}
}