[ https://issues.apache.org/jira/browse/LOG4J2-1349?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15346312#comment-15346312 ]
Remko Popma edited comment on LOG4J2-1349 at 6/24/16 12:09 AM: --------------------------------------------------------------- The current {{ThreadContext}} map implementation is a copy-on-write data structure. This is efficient because the number of _reads_ vastly outnumbers the number of _writes_. Every time a message is logged, the current ThreadContext map is passed to the LogEvent as is. This is safe because this map is immutable: it is replaced, not modified, when the user calls ThreadContext.put(key, somevalue). The drawback is that a copy-on-write data structure is not garbage-free. A garbage-free ThreadContext map would have to be a mutable data structure. To ensure that LogEvents can safely be passed off to other threads, the LogEvent cannot have a direct reference to the ThreadContext map. Instead, the data from the ThreadContext map would need to be copied into the LogEvent's context map. For this to be garbage-free, LogEvent needs a different data structure to carry context map data. Currently LogEvent implementations use a {{java.util.Map<String, String>}} for this. The JDK Map is not an easy data structure to make garbage-free. It would also be nice to have the ability in LogEvent to carry data of any type. One idea is to introduce a small interface that is general enough to be map-like but can be implemented in a garbage-free manner. LogEvent implementations would have an instance of this interface instead of the current {{java.util.Map<String, String> contextMap}} attribute. Something like this: {code} interface CustomData<K, V> { /** Called to implement {@link LogEvent#getContextMap()}. */ Map<String, String> asMap(); /** Put key-value pair into the table. Remove key if value is null. */ void put(K key, V value); /** Returns the value for the specified key. */ V getValue(K key); /** Number of key-value pairs. */ int size(); /** Removes all key-value pairs. */ void clear(); // Instead of Iterators, use an index-based approach. /** Returns the index of the specified key. */ int indexOfKey(K key); /** Returns the i-th key. */ K getKeyAt(int i); /** Returns the value for the i-th key. */ V getValueAt(int i); } {code} The LogEvent interface would have an additional method {{getCustomData() : CustomData<K, V>}} that gives downstream components direct access to the new data structure. Existing downstream components would still be able to call {{logEvent.getContextMap()}} to get a {{Map<String, String>}} view of the context map data and this would work as expected (although it may not be garbage-free). was (Author: rem...@yahoo.com): The current {{ThreadContext}} map implementation is a copy-on-write data structure. This is efficient because the number of _reads_ vastly outnumbers the number of _writes_. Every time a message is logged, the current ThreadContext map is passed to the LogEvent as is. This is safe because this map is immutable: it is replaced, not modified, when the user calls ThreadContext.put(key, somevalue). The drawback is that a copy-on-write data structure is not garbage-free. A garbage-free ThreadContext map would have to be a mutable data structure. To ensure that LogEvents can safely be passed off to other threads, the LogEvent cannot have a direct reference to the ThreadContext map. Instead, the data from the ThreadContext map would need to be copied into the LogEvent's context map. For this to be garbage-free, LogEvent needs a different data structure to carry context map data. Currently LogEvent implementations use a {{java.util.Map<String, String>}} for this. The JDK Map is not an easy data structure to make garbage-free. It would also be nice to have the ability in LogEvent to carry data of any type. One idea is to introduce a small interface that is general enough to be map-like but can be implemented in a garbage-free manner. LogEvent implementations would have an instance of this interface instead of the current {{java.util.Map<String, String> contextMap}} attribute. Something like this: {code} interface CustomData<K, V> { /** Called to implement {@link LogEvent#getContextMap()}. */ Map<String, String> asMap(); /** Put key-value pair into the table. Remove key if value is null. */ void put(K key, V value); /** Returns the value for the specified key. */ V getValue(K key); /** Number of key-value pairs. */ int size(); /** Removes all key-value pairs. */ void clear(); // Instead of Iterators, use an index-based approach. /** Returns the index of the specified key. */ int indexOfKey(K key); /** Returns the i-th key. */ K getKey(int i); /** Returns the value for the i-th key. */ V getValueAt(int i); } {code} The LogEvent interface would have an additional method {{getCustomData() : CustomData<K, V>}} that gives downstream components direct access to the new data structure. Existing downstream components would still be able to call {{logEvent.getContextMap()}} to get a {{Map<String, String>}} view of the context map data and this would work as expected. > Garbage-free ThreadContext map and stack > ---------------------------------------- > > 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 > 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: log4j-dev-unsubscr...@logging.apache.org For additional commands, e-mail: log4j-dev-h...@logging.apache.org