summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@rabbitmq.com>2011-06-03 14:05:39 +0100
committerMatthias Radestock <matthias@rabbitmq.com>2011-06-03 14:05:39 +0100
commitbc0233a9aa74bf30c2cf65ae1d90ca4bee28f208 (patch)
treecd6b2d0fbe352d762873479e639a685803833134
parent4013096a30291bd1f98b6016e018f405c7dbe0f8 (diff)
downloadrabbitmq-server-bug24151.tar.gz
optimise routing by bypassing mnesia:dirty_selectbug24151
...and going straight to an ets:select instead
-rw-r--r--src/rabbit_router.erl35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/rabbit_router.erl b/src/rabbit_router.erl
index f6a1c92f..8f166672 100644
--- a/src/rabbit_router.erl
+++ b/src/rabbit_router.erl
@@ -84,21 +84,18 @@ match_bindings(SrcName, Match) ->
mnesia:async_dirty(fun qlc:e/1, [Query]).
match_routing_key(SrcName, [RoutingKey]) ->
- MatchHead = #route{binding = #binding{source = SrcName,
+ find_routes(#route{binding = #binding{source = SrcName,
destination = '$1',
key = RoutingKey,
_ = '_'}},
- mnesia:dirty_select(rabbit_route, [{MatchHead, [], ['$1']}]);
+ []);
match_routing_key(SrcName, [_|_] = RoutingKeys) ->
- Condition = list_to_tuple(['orelse' | [{'=:=', '$2', RKey} ||
- RKey <- RoutingKeys]]),
- MatchHead = #route{binding = #binding{source = SrcName,
+ find_routes(#route{binding = #binding{source = SrcName,
destination = '$1',
key = '$2',
_ = '_'}},
- mnesia:dirty_select(rabbit_route, [{MatchHead, [Condition], ['$1']}]).
-
-
+ [list_to_tuple(['orelse' | [{'=:=', '$2', RKey} ||
+ RKey <- RoutingKeys]])]).
%%--------------------------------------------------------------------
@@ -117,3 +114,25 @@ lookup_qpids(QNames) ->
[] -> QPids
end
end, [], QNames).
+
+%% Normally we'd call mnesia:dirty_select/2 here, but that is quite
+%% expensive due to
+%%
+%% 1) general mnesia overheads (figuring out table types and
+%% locations, etc). We get away with bypassing these because we know
+%% that the table
+%% - is not the schema table
+%% - has a local ram copy
+%% - does not have any indices
+%%
+%% 2) 'fixing' of the table with ets:safe_fixtable/2, which is wholly
+%% unnecessary. According to the ets docs (and the code in erl_db.c),
+%% 'select' is safe anyway ("Functions that internally traverse over a
+%% table, like select and match, will give the same guarantee as
+%% safe_fixtable.") and, furthermore, even the lower level iterators
+%% ('first' and 'next') are safe on ordered_set tables ("Note that for
+%% tables of the ordered_set type, safe_fixtable/2 is not necessary as
+%% calls to first/1 and next/2 will always succeed."), which
+%% rabbit_route is.
+find_routes(MatchHead, Conditions) ->
+ ets:select(rabbit_route, [{MatchHead, Conditions, ['$1']}]).