On 23/09/2012 12:04, Rainer Jung wrote:
> 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())?

No, I haven't tested that.

>> +            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 ?

Yes. Thanks. I hard-coded it to test, added all the configuration and
forgot the important bit. Good catch.

> "<" -> "<=" ?

To align with the docs, yes. I'll fix that too.

>> +        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));

I'll switch that too.

Cheers,

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to