From 34cc0e5d82f83105eb46be206e62e81673365666 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 10 Jan 2013 09:39:56 +0100 Subject: [PATCH] Optimized memory usage of AttributesMap. Attributes are used rarely, so AttributesMap was creating a ConcurrentHashMap that was never used. In cases where AttributesMap is heavily used (for example CometD) this proved to save a significant amount of memory footprint. --- .../org/eclipse/jetty/util/AttributesMap.java | 136 ++++++++---------- 1 file changed, 57 insertions(+), 79 deletions(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java index 9219e3f6392..ee2e57f6e0c 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/AttributesMap.java @@ -25,144 +25,122 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicReference; -/* ------------------------------------------------------------ */ -/** AttributesMap. - * - * - */ public class AttributesMap implements Attributes { - protected final Map _map; + private final AtomicReference> _map = new AtomicReference<>(); - /* ------------------------------------------------------------ */ public AttributesMap() { - _map=new ConcurrentHashMap(); - } - - /* ------------------------------------------------------------ */ - public AttributesMap(Map map) - { - _map=map; } - /* ------------------------------------------------------------ */ - public AttributesMap(AttributesMap map) + public AttributesMap(AttributesMap attributes) { - _map=new ConcurrentHashMap(map._map); + ConcurrentMap map = attributes.map(); + if (map != null) + _map.set(new ConcurrentHashMap<>(map)); } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#removeAttribute(java.lang.String) - */ + + private ConcurrentMap map() + { + return _map.get(); + } + + private ConcurrentMap ensureMap() + { + while (true) + { + ConcurrentMap map = map(); + if (map != null) + return map; + map = new ConcurrentHashMap<>(); + if (_map.compareAndSet(null, map)) + return map; + } + } + @Override public void removeAttribute(String name) { - _map.remove(name); + Map map = map(); + if (map != null) + map.remove(name); } - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#setAttribute(java.lang.String, java.lang.Object) - */ @Override public void setAttribute(String name, Object attribute) { - if (attribute==null) - _map.remove(name); + if (attribute == null) + removeAttribute(name); else - _map.put(name, attribute); + ensureMap().put(name, attribute); } - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#getAttribute(java.lang.String) - */ @Override public Object getAttribute(String name) { - return _map.get(name); + Map map = map(); + return map == null ? null : map.get(name); } - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#getAttributeNames() - */ @Override public Enumeration getAttributeNames() { - return Collections.enumeration(_map.keySet()); + return Collections.enumeration(keySet()); } - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#getAttributeNames() - */ - public Set getAttributeNameSet() - { - return _map.keySet(); - } - - /* ------------------------------------------------------------ */ public Set> getAttributeEntrySet() { - return _map.entrySet(); + Map map = map(); + return map == null ? Collections.>emptySet() : map.entrySet(); } - - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#getAttributeNames() - */ + public static Enumeration getAttributeNamesCopy(Attributes attrs) { if (attrs instanceof AttributesMap) - return Collections.enumeration(((AttributesMap)attrs)._map.keySet()); - - List names = new ArrayList(); + return Collections.enumeration(((AttributesMap)attrs).keySet()); + + List names = new ArrayList<>(); names.addAll(Collections.list(attrs.getAttributeNames())); return Collections.enumeration(names); } - /* ------------------------------------------------------------ */ - /* - * @see org.eclipse.jetty.util.Attributes#clear() - */ @Override public void clearAttributes() { - _map.clear(); + Map map = map(); + if (map != null) + map.clear(); } - - /* ------------------------------------------------------------ */ + public int size() { - return _map.size(); + Map map = map(); + return map == null ? 0 : map.size(); } - - /* ------------------------------------------------------------ */ + @Override public String toString() { - return _map.toString(); + Map map = map(); + return map == null ? "{}" : map.toString(); } - - /* ------------------------------------------------------------ */ - public Set keySet() + + private Set keySet() { - return _map.keySet(); + Map map = map(); + return map == null ? Collections.emptySet() : map.keySet(); } - - /* ------------------------------------------------------------ */ + public void addAll(Attributes attributes) { Enumeration e = attributes.getAttributeNames(); while (e.hasMoreElements()) { - String name=e.nextElement(); - setAttribute(name,attributes.getAttribute(name)); + String name = e.nextElement(); + setAttribute(name, attributes.getAttribute(name)); } } - }