]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Improve performance of get_active_networks_info
authoryangxurong <yangxurong@huawei.com>
Tue, 11 Nov 2014 09:06:22 +0000 (17:06 +0800)
committeryangxurong <yangxurong@huawei.com>
Mon, 15 Dec 2014 08:20:21 +0000 (16:20 +0800)
RPC 'get_active_networks_info' currently uses nested loop to fill
the network structure with subnet and port info. Speed up this
operation by using itertools.groupby.

Change-Id: If765dd8f2f8010b79eb168179a64dccf940e9cbb
Closes-Bug: #1390356

neutron/api/rpc/handlers/dhcp_rpc.py
neutron/tests/unit/test_dhcp_rpc.py

index 9673a65d5af58490ec55559f62b11b441f561db5..80b7e3f66b9b5ee9339afc0c5a60009bab9a6281 100644 (file)
@@ -13,6 +13,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import itertools
+import operator
+
 from oslo.config import cfg
 from oslo.db import exception as db_exc
 from oslo import messaging
@@ -94,6 +97,14 @@ class DhcpRpcCallback(object):
         nets = self._get_active_networks(context, **kwargs)
         return [net['id'] for net in nets]
 
+    def _group_by_network_id(self, res):
+        grouped = {}
+        keyfunc = operator.itemgetter('network_id')
+        for net_id, values in itertools.groupby(sorted(res, key=keyfunc),
+                                                keyfunc):
+            grouped[net_id] = list(values)
+        return grouped
+
     def get_active_networks_info(self, context, **kwargs):
         """Returns all the networks/subnets/ports in system."""
         host = kwargs.get('host')
@@ -105,11 +116,11 @@ class DhcpRpcCallback(object):
         filters['enable_dhcp'] = [True]
         subnets = plugin.get_subnets(context, filters=filters)
 
+        grouped_subnets = self._group_by_network_id(subnets)
+        grouped_ports = self._group_by_network_id(ports)
         for network in networks:
-            network['subnets'] = [subnet for subnet in subnets
-                                  if subnet['network_id'] == network['id']]
-            network['ports'] = [port for port in ports
-                                if port['network_id'] == network['id']]
+            network['subnets'] = grouped_subnets.get(network['id'], [])
+            network['ports'] = grouped_ports.get(network['id'], [])
 
         return networks
 
index 2c4c5c9e6e7c08068e49b59d3907695457e58fc7..e0ebe65e78224383a12265699c3681d66aa877fb 100644 (file)
@@ -47,6 +47,28 @@ class TestDhcpRpcCallback(base.BaseTestCase):
 
         self.assertEqual(len(self.log.mock_calls), 1)
 
+    def test_group_by_network_id(self):
+        port1 = {'network_id': 'a'}
+        port2 = {'network_id': 'b'}
+        port3 = {'network_id': 'a'}
+        grouped_ports = self.callbacks._group_by_network_id(
+                                                        [port1, port2, port3])
+        expected = {'a': [port1, port3], 'b': [port2]}
+        self.assertEqual(expected, grouped_ports)
+
+    def test_get_active_networks_info(self):
+        plugin_retval = [{'id': 'a'}, {'id': 'b'}]
+        self.plugin.get_networks.return_value = plugin_retval
+        port = {'network_id': 'a'}
+        subnet = {'network_id': 'b'}
+        self.plugin.get_ports.return_value = [port]
+        self.plugin.get_subnets.return_value = [subnet]
+        networks = self.callbacks.get_active_networks_info(mock.Mock(),
+                                                           host='host')
+        expected = [{'id': 'a', 'subnets': [], 'ports': [port]},
+                    {'id': 'b', 'subnets': [subnet], 'ports': []}]
+        self.assertEqual(expected, networks)
+
     def _test__port_action_with_failures(self, exc=None, action=None):
         port = {
             'network_id': 'foo_network_id',