server: Rework filter_interfaces() for less lambda

The pyflame flamegraphs were highlighting the lambdas as the performance
bottleneck, so break them out procedural style to gain a better
understanding of where the problem lies.

Further, the functional style was almost impenetrable with respect to
the procedural equivalent. When the function we're executing has full
visibility of the transform pipeline the procedural style reduces the
cognitive load (at least, for me) even if it is stateful in some sense.

Change-Id: I444fcc6daedfc7f53932bc7acc950e4f60ab151f
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/obmc/mapper/server.py b/obmc/mapper/server.py
index 24e5bbb..8d23a4c 100644
--- a/obmc/mapper/server.py
+++ b/obmc/mapper/server.py
@@ -560,33 +560,37 @@
 
     @staticmethod
     def filter_interfaces(item, ifaces):
+        return ObjectMapper._filter_interfaces(item, set(ifaces))
+
+    @staticmethod
+    def _filter_interfaces(item, ifaces):
         if isinstance(item, dict):
             # Called with a single object.
             if not ifaces:
                 return item
 
-            # Remove interfaces from a service that
-            # aren't in a filter.
-            svc_map = lambda svc: (svc[0], set(ifaces).intersection(svc[1]))
+            filtered = dict()
+            for k, v in item.items():
+                isec = ifaces.intersection(v)
+                if isec:
+                    filtered[k] = isec
 
-            # Remove services where no interfaces remain after mapping.
-            svc_filter = lambda svc: svc[1]
-
-            obj_map = lambda o: tuple(*filter(svc_filter, map(svc_map, [o])))
-
-            return dict(x for x in map(obj_map, item.items()) if x)
+            return filtered
 
         # Called with a list of path/object tuples.
         if not ifaces:
             return dict(item)
 
-        obj_map = lambda x: (
-            x[0],
-            ObjectMapper.filter_interfaces(
-                x[1],
-                ifaces))
+        if not item:
+            return dict()
 
-        return dict([x for x in map(obj_map, iter(item or [])) if x[1]])
+        filtered = dict()
+        for i in item:
+            children = ObjectMapper._filter_interfaces(i[1], ifaces)
+            if children:
+                filtered[i[0]] = children
+
+        return filtered
 
     @dbus.service.method(obmc.mapper.MAPPER_IFACE, 'sas', 'a{sas}')
     def GetObject(self, path, interfaces):