[ https://issues.apache.org/jira/browse/LOG4J2-1447?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15401881#comment-15401881 ]
Remko Popma commented on LOG4J2-1447: ------------------------------------- Initial perf test attempt. (Cannot commit from work) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Fork(1) @State(Scope.Benchmark) public class ArrayContextDataVsHashMapBenchmark { //@Param({"1", "2", "5", "11", "23", "47", "95", "191", "383"}) @Param({"1", "5", "50", "500"}) public int count; //@Param({"5", "50"}) @Param({"20"}) public int length; private String[] keys; private static Object value = new Object(); private HashMap<String, Object> map; private ArrayContextData contextData; private HashMap<String, Object> populatedMap; private ArrayContextData populatedContextData; @Setup public void setup() { contextData = new ArrayContextData(); map = new HashMap<>(); keys = new String[count]; Random r = new Random(); for (int j = 0; j < keys.length; j++) { char[] str = new char[length]; for (int i = 0; i < str.length; i++) { str[i] = (char) r.nextInt(); } keys[j] = new String(str); } populatedMap = new HashMap<>(); for (int i = 0; i < count; i++) { populatedMap.put(keys[i], value); } populatedContextData = new ArrayContextData(); for (int i = 0; i < count; i++) { populatedContextData.putValue(keys[i], value); } } @Benchmark public ArrayContextData putAllContextData() { contextData.clear(); contextData.putAll(populatedContextData); return contextData; } @Benchmark public Map putAllMap() { map.clear(); map.putAll(populatedMap); return map; } @Benchmark public ArrayContextData cloneContextData() { return new ArrayContextData(populatedContextData); } @Benchmark public Map cloneMap() { return new HashMap(populatedMap); } static TriConsumer<String, Object, int[]> COUNTER = new TriConsumer<String, Object, int[]>() { @Override public void accept(String s, Object o, int[] result) { result[0] += s.hashCode() + o.hashCode(); } }; @Benchmark public int iterateContextDataTriConsumer() { final int[] result = {0}; populatedContextData.forEach(COUNTER, result); return result[0]; } @Benchmark public int iterateContextDataBiConsumer() { final int[] result = {0}; populatedContextData.forEach(new BiConsumer<String, Object>() { @Override public void accept(String s, Object o) { result[0] += s.hashCode() + o.hashCode(); } }); return result[0]; } @Benchmark public int iterateMap() { final int[] result = {0}; for (Map.Entry<String, Object> entry : populatedMap.entrySet()) { result[0] += entry.getKey().hashCode() + entry.getValue().hashCode(); } return result[0]; } @Benchmark public int getContextData() { String[] theKeys = keys; int c = count; int result = 0; for (int i = 0; i < c; i++) { Object val = populatedContextData.getValue(theKeys[i]); result += val.hashCode();// + theKeys[i].hashCode(); } return result; } @Benchmark public int getMap() { String[] theKeys = keys; int c = count; int result = 0; for (int i = 0; i < c; i++) { Object val = populatedMap.get(theKeys[i]); result += val.hashCode();// + theKeys[i].hashCode(); } return result; } @Benchmark public int putContextData() { String[] theKeys = keys; int c = count; for (int i = 0; i < c; i++) { contextData.putValue(theKeys[i], value); } return contextData.size(); } @Benchmark public int putMap() { String[] theKeys = keys; int c = count; for (int i = 0; i < c; i++) { map.put(theKeys[i], value); } return map.size(); } } > Garbage-free data structure for LogEvent's context map data > ----------------------------------------------------------- > > Key: LOG4J2-1447 > URL: https://issues.apache.org/jira/browse/LOG4J2-1447 > Project: Log4j 2 > Issue Type: Improvement > Components: Core > Affects Versions: 2.6.1 > Reporter: Remko Popma > Assignee: Remko Popma > Fix For: 2.7 > > > With each logging call, context map data is copied from the {{ThreadContext}} > map into the {{LogEvent}}. > The LogEvent interface exposes this data via the {{getContextMap() : > Map<String, String>}} method, and this is implementated by storing the data > in a Map<String, String>. 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. > The interface could look something like this: > {code} > interface ContextData<String, 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(String key, V value); > /** Returns the value for the specified key. */ > V getValue(String key); > /** Number of key-value pairs. */ > int size(); > /** Removes all key-value pairs. */ > void clear(); > // Instead of Iterators, client code provides the consumer. > /** > * Performs the given action for each key-value pair in this data > structure > * until all entries have been processed or the action throws an > exception. > */ > void forEach(BiConsumer<String, ? super V> action); > } > /** > * An operation that accepts two input arguments and returns no result. > */ > interface BiConsumer<T,U> { > /** Performs the operation given the specified arguments. */ > void accept(T t, U u); > } > {code} > The LogEvent interface would have an additional method {{getContextData() : > ContextData<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. -- 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