Hi Mark,
On 23.09.2012 11:43, ma...@apache.org wrote:
Author: markt
Date: Sun Sep 23 09:43:43 2012
New Revision: 1388991
URL: http://svn.apache.org/viewvc?rev=1388991&view=rev
Log:
Use CharBuffer rather than StringBuilder to build the access log message to:
- save a char[] to String conversion and the associated garbage
- allow buffers to be recycled also saving garbage
Reduces allocations due to the AccessLog from 43% to 27% of the overall
allocations
Modified:
tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
tomcat/trunk/java/org/apache/catalina/valves/ExtendedAccessLogValve.java
tomcat/trunk/webapps/docs/config/valve.xml
Modified: tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java?rev=1388991&r1=1388990&r2=1388991&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java (original)
+++ tomcat/trunk/java/org/apache/catalina/valves/AccessLogValve.java Sun Sep 23
09:43:43 2012
@@ -570,13 +573,28 @@ public class AccessLogValve extends Valv
*/
protected boolean requestAttributesEnabled = false;
- // ------------------------------------------------------------- Properties
+ /**
+ * Buffer pool used for log message generation. Pool used to reduce garbage
+ * generation.
+ */
+ private Queue<CharBuffer> charBuffers = new ConcurrentLinkedQueue<>();
/**
- * @return Returns the enabled.
+ * Log message buffers are usually recycled and re-used. To prevent
+ * excessive memory usage, if a buffer grows beyond this size it will be
+ * discarded. The default is 256 characters. This should be set to larger
+ * than the typical access log message size.
*/
- public boolean getEnabled() {
- return enabled;
+ private int maxLogMessageBufferSize = 256;
+
+ // ------------------------------------------------------------- Properties
+
+ public int getMaxLogMessageBufferSize() {
+ return maxLogMessageBufferSize;
+ }
+
+ public void setMaxLogMessageBufferSize(int maxLogMessageBufferSize) {
+ this.maxLogMessageBufferSize = maxLogMessageBufferSize;
}
/**
@@ -596,6 +614,13 @@ public class AccessLogValve extends Valv
}
/**
+ * @return Returns the enabled.
+ */
+ public boolean getEnabled() {
+ return enabled;
+ }
+
+ /**
* @param enabled
* The enabled to set.
*/
@@ -933,13 +958,23 @@ public class AccessLogValve extends Valv
long start = request.getCoyoteRequest().getStartTime();
Date date = getDate(start + time);
- StringBuilder result = new StringBuilder(128);
+ CharBuffer result = charBuffers.poll();
+ if (result == null) {
I'm just curious here: do you already know whether using a direct buffer
would be better or worse (e.g.
ByteBuffer.allocateDirect(128).asCharBuffer())?
+ result = CharBuffer.allocate(128);
+ }
for (int i = 0; i < logElements.length; i++) {
logElements[i].addElement(result, date, request, response, time);
}
- log(result.toString());
+ result.flip();
+ log(result);
+
+ // TODO - Make this configurable
256 -> maxLogMessageBufferSize ?
"<" -> "<=" ?
+ if (result.length() < 256) {
+ result.clear();
+ charBuffers.add(result);
+ }
}
@@ -1676,19 +1713,19 @@ public class AccessLogValve extends Valv
}
@Override
- public void addElement(StringBuilder buf, Date date, Request request,
+ public void addElement(CharBuffer buf, Date date, Request request,
Response response, long time) {
if (millis) {
- buf.append(time);
+ buf.append(Long.toString(time));
} else {
// second
- buf.append(time / 1000);
+ buf.append(Long.toString(time / 1000));
buf.append('.');
I think the following code originally was meant to improve performance
by slicing the 3 digit number "remains" into a sequence of digits. I
expect the below to be a bit more efficient and less complicated now
that Long.toString() is used:
int remains = (int) (time % 1000);
- buf.append(remains / 100);
+ buf.append(Long.toString(remains / 100));
remains = remains % 100;
- buf.append(remains / 10);
- buf.append(remains % 10);
+ buf.append(Long.toString(remains / 10));
+ buf.append(Long.toString(remains % 10));
buf.append(Long.toString(time % 1000));
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org