[ 
https://issues.apache.org/jira/browse/LOG4J2-1349?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15350000#comment-15350000
 ] 

Remko Popma commented on LOG4J2-1349:
-------------------------------------

About the worse performance: I think I did not present that well. True, 
garbage-free is not _always_ better, but by a small margin and in rare cases. 
Perhaps I over-emphasized them in the performance docs. Note that the 
garbage-free initiative has made Log4j 2.6 faster than 2.5 in all tests.

Overall, the feedback on Log4j going gc-free has been overwhelmingly positive, 
so I don't think we are on the wrong track.

On the other hand, I understand that you want to keep complexity within reason. 

About my proposal, the problem here is that context key-value data can only be 
accessed as a java.util.Map. For the stack, ThreadContext exposes the 
ContextStack interface, but the equivalent ThreadContextMap SPI interface 
cannot be accessed from ThreadContext. 

I want to add a method {{getThreadContextMap()}} to ThreadContext, so that the 
context data injector in LOG4J2-1010 can look like this:

{code}
public class DefaultContextDataInjector implements ContextDataInjector {
    @Override
    public void injectContextData(final List<Property> properties, final 
LogEvent event) {
        copyProperties(properties, event.getContextData());
        final ThreadContextMap contextMap = 
ThreadContext.getThreadContextMap(); // <-- the new method
        copyThreadContextMap(contextMap, event.getContextData());
    }

    private void copyThreadContextMap(final ThreadContextMap contextMap,
            final ContextData<Object, Object> contextData) {

        if (contextMap instanceof IndexedMap) { // garbage-free
            IndexedMap<Object, Object> indexedMap = (IndexedMap<Object, 
Object>) contextMap;
            for (int i = 0; i < indexedMap.size(); i++) {
                contextData.put(indexedMap.getKeyAt(i), 
indexedMap.getValueAt(i));
            }
        } else { // classic
            final Map<String, String> map = contextMap.getImmutableMapOrNull();
            if (map != null) {
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    contextData.put(entry.getKey(), entry.getValue());
                }
            }
        }
    }

    private void copyProperties(final List<Property> properties, final 
ContextData<Object, Object> contextData) {
        if (properties != null) {
            for (int i = 0; i < properties.size(); i++) {
                final Property prop = properties.get(i);
                contextData.put(prop.getName(), prop.getValue());
            }
        }
    }
}

interface IndexedMap<K, V> {
    int size();
    K getKeyAt(i);
    V getValueAt(i);
}
{code}


> Garbage-free ThreadContext map
> ------------------------------
>
>                 Key: LOG4J2-1349
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-1349
>             Project: Log4j 2
>          Issue Type: Improvement
>          Components: API
>    Affects Versions: 2.5
>            Reporter: Remko Popma
>            Assignee: Remko Popma
>             Fix For: 2.7
>
>
> The current ThreadContext map and stack implementations allocate temporary 
> objects. This ticket is to investigate and track the work for alternative 
> implementations that are garbage-free.
> Both DefaultThreadContextMap and DefaultThreadContextStack are copy-on-write 
> data structures: each modification replaces the ThreadLocal object with a 
> modified copy. The advantage of this approach is that there is no need to 
> make a copy for each LogEvent.
> Also, DefaultThreadContextMap uses a JDK map, the JDK collections tend to 
> allocate a lot of temporary objects.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to