]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Improve performance of _get_security_group_member_ips
authorEugene Nikanorov <enikanorov@mirantis.com>
Mon, 9 Mar 2015 09:04:34 +0000 (12:04 +0300)
committerEugene Nikanorov <enikanorov@mirantis.com>
Tue, 10 Mar 2015 07:55:05 +0000 (10:55 +0300)
Use set operations instead of using list.
Currently complexity of the method is O(n^2) where n is
amount of ips (amount of VMs in the network).
When amount of VM is big (large L2 domain), this method
can significantly load the controller.
Reduce method complexity to O(n) on average.

Change-Id: If1660e8227e5c5cd80d49ebcc6a2e06d33d31939
Closes-Bug: #1429753

neutron/api/rpc/handlers/securitygroups_rpc.py
neutron/db/securitygroups_rpc_base.py
neutron/tests/unit/test_security_groups_rpc.py

index d1006d0158f64fad6d1bbd9fe59d8ace0f7fbaf1..4d4d0fea82ad50ae74528bcc6dafa2351cc2148e 100644 (file)
@@ -71,9 +71,11 @@ class SecurityGroupServerRpcCallback(object):
         :returns:
         sg_info{
           'security_groups': {sg_id: [rule1, rule2]}
-          'sg_member_ips': {sg_id: {'IPv4': [], 'IPv6': []}}
+          'sg_member_ips': {sg_id: {'IPv4': set(), 'IPv6': set()}}
           'devices': {device_id: {device_info}}
         }
+
+        Note that sets are serialized into lists by rpc code.
         """
         devices_info = kwargs.get('devices')
         ports = self._get_devices_info(devices_info)
index e8f9292c71d1b526267d66eaac600566408ee16a..728312b535071f89f7d1799a079de8a4921e9431 100644 (file)
@@ -194,7 +194,8 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
                 if remote_gid not in remote_security_group_info:
                     remote_security_group_info[remote_gid] = {}
                 if ethertype not in remote_security_group_info[remote_gid]:
-                    remote_security_group_info[remote_gid][ethertype] = []
+                    # this set will be serialized into a list by rpc code
+                    remote_security_group_info[remote_gid][ethertype] = set()
 
             direction = rule_in_db['direction']
             rule_dict = {
@@ -228,9 +229,8 @@ class SecurityGroupServerRpcMixin(sg_db.SecurityGroupDbMixin):
         for sg_id, member_ips in ips.items():
             for ip in member_ips:
                 ethertype = 'IPv%d' % netaddr.IPNetwork(ip).version
-                if (ethertype in sg_info['sg_member_ips'][sg_id]
-                    and ip not in sg_info['sg_member_ips'][sg_id][ethertype]):
-                    sg_info['sg_member_ips'][sg_id][ethertype].append(ip)
+                if ethertype in sg_info['sg_member_ips'][sg_id]:
+                    sg_info['sg_member_ips'][sg_id][ethertype].add(ip)
         return sg_info
 
     def _select_rules_for_ports(self, context, ports):
index 50b8936e5afcd61a68d612c305c4e290228d255f..138e742e55adfb7abd1878ebdc9ecd25430cfd70 100644 (file)
@@ -490,8 +490,8 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
                          'remote_group_id': sg2_id}
                     ]},
                     'sg_member_ips': {sg2_id: {
-                        'IPv4': [u'10.0.0.3'],
-                        'IPv6': [],
+                        'IPv4': set([u'10.0.0.3']),
+                        'IPv6': set(),
                     }}
                 }
                 self.assertEqual(expected['security_groups'],
@@ -626,7 +626,7 @@ class SGServerRpcCallBackTestCase(test_sg.SecurityGroupDBTestCase):
                          'remote_group_id': sg1_id}
                     ]},
                     'sg_member_ips': {sg1_id: {
-                        'IPv6': [],
+                        'IPv6': set(),
                     }}
                 }
                 self.assertEqual(expected['security_groups'],