Improve performance of _get_security_group_member_ips

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
This commit is contained in:
Eugene Nikanorov 2015-03-09 12:04:34 +03:00
parent ebc1469a7e
commit 2db7182570
3 changed files with 10 additions and 8 deletions

View 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)

View 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):

View 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'],