Fixing the filter in get MTU by network list query.

Based on the observation that a call to sync_routers can be slow
(10-15 seconds for one virtual router), and that profiling data show
that a significant amount of time is spent in function
_get_mtus_by_network_list, this change fixes incorrect the database
query for getting information about networks.

What changed:
- before: SQL query spent time O(#networks in database)
          (select all exists networks from database)
- after : SQL query spent time O(#network_ids passed to the function)
          (select only needed networks)

A basic test shows a drastic improvements, from 2 second to around
~0.2 second, in the processing of a _get_mtus_by_network_list call
with 300 networks in database.

Change-Id: Id50d1aaddd0d2a1110502de9c5b974063daa296a
Closes-Bug: #1748888
This commit is contained in:
Vadim ponomarev 2018-02-12 16:48:29 +03:00 committed by Vadim Ponomarev
parent 0d594f7e14
commit d15244ab4f
2 changed files with 17 additions and 1 deletions

View File

@ -1716,7 +1716,7 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase,
def _get_mtus_by_network_list(self, context, network_ids):
if not network_ids:
return {}
filters = {'network_id': network_ids}
filters = {'id': network_ids}
fields = ['id', 'mtu']
networks = self._core_plugin.get_networks(context, filters=filters,
fields=fields)

View File

@ -85,6 +85,22 @@ class TestL3_NAT_dbonly_mixin(base.BaseTestCase):
'address_scope_id': mock.sentinel.address_scope_id,
'network_id': mock.sentinel.network_id}]}, subnets)
def test__get_mtus_by_network_list(self):
"""Basic test that the query get_networks is correctly"""
network = {'id': mock.sentinel.network_id,
'name': mock.sentinel.name,
'mtu': mock.sentinel.mtu}
with mock.patch.object(directory, 'get_plugin') as get_p:
get_p().get_networks.return_value = [network]
result = self.db._get_mtus_by_network_list(
mock.sentinel.context, [mock.sentinel.network_id])
get_p().get_networks.assert_called_once_with(
mock.sentinel.context,
filters={'id': [mock.sentinel.network_id]},
fields=['id', 'mtu'])
self.assertEqual({mock.sentinel.network_id: mock.sentinel.mtu},
result)
def test__populate_ports_for_subnets_none(self):
"""Basic test that the method runs correctly with no ports"""
ports = []