Use ImmutableMap for single namespaces 64/87164/3
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 27 Jan 2020 11:31:15 +0000 (12:31 +0100)
committerRobert Varga <nite@hq.sk>
Mon, 27 Jan 2020 12:49:14 +0000 (12:49 +0000)
It is extremely common for statement contexts to have exactly one
namespace (i.e. ChildSchemaNodeNamespace). Tracking that in a HashMap
is not very memory-efficient (nor performance-efficient), as we will
end up allocating all the HashMap internals.

Separate out the single-namespace case and use an ImmutableMap singleton
to hold the namespace -- which saves ~65MiB in a reference test case
accounding for ~6% of scratch memory used (~3% total used).

JIRA: YANGTOOLS-652
Change-Id: Ie2b1faeb4c966c20be0818d3b54aa7c8367f0c58
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/NamespaceStorageSupport.java

index 7f15c0615504292b8e546a2047096e1b5050704a..8ee75f996dae24866275c362bc9d958a528b0301 100644 (file)
@@ -136,10 +136,22 @@ abstract class NamespaceStorageSupport implements NamespaceStorageNode {
             checkLocalNamespaceAllowed(type);
             ret = new HashMap<>(1);
 
-            if (namespaces.isEmpty()) {
-                namespaces = new HashMap<>(1);
+            switch (namespaces.size()) {
+                case 0:
+                    // We typically have small population of namespaces, use a singleton map
+                    namespaces = ImmutableMap.of(type, ret);
+                    break;
+                case 1:
+                    // Alright, time to grow to a full HashMap
+                    final Map<Class<?>, Map<?,?>> newNamespaces = new HashMap<>(4);
+                    final Entry<Class<?>, Map<?, ?>> entry = namespaces.entrySet().iterator().next();
+                    newNamespaces.put(entry.getKey(), entry.getValue());
+                    namespaces = newNamespaces;
+                    // fall through
+                default:
+                    // Already expanded, just put the new namespace
+                    namespaces.put(type, ret);
             }
-            namespaces.put(type, ret);
         }
 
         return ret;