You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/01 11:10:20 UTC
[24/35] git commit: Minor optimizations for couch_event_registry
Minor optimizations for couch_event_registry
Mostly making use of batch operations with match and multiple inserts. I
tried some more aggressive optimizations before these but those only
managed to make things slower. The major thing I tried was to use the
zero timeout trick to collect messages and then batch load those into
ets but that only managed to cause a large number of timeouts.
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-event/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-event/commit/2ad40edc
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-event/tree/2ad40edc
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-event/diff/2ad40edc
Branch: refs/heads/windsor-merge
Commit: 2ad40edc94130e91cf0f96b55de6dadbf2cada42
Parents: a8b378b
Author: Paul J. Davis <pa...@gmail.com>
Authored: Fri Apr 26 13:52:12 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Wed Jul 30 17:44:23 2014 +0100
----------------------------------------------------------------------
src/couch_event_registry.erl | 83 +++++++++++++++++++++++++--------------
1 file changed, 53 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-event/blob/2ad40edc/src/couch_event_registry.erl
----------------------------------------------------------------------
diff --git a/src/couch_event_registry.erl b/src/couch_event_registry.erl
index 19e70c2..adea994 100644
--- a/src/couch_event_registry.erl
+++ b/src/couch_event_registry.erl
@@ -57,63 +57,86 @@ terminate(_Reason, _St) ->
handle_call({register, Pid, DbNames}, _From, St) ->
- lists:foreach(fun(DbName) ->
- ets:insert(?REGISTRY_TABLE, #client{dbname=DbName, pid=Pid})
- end, DbNames),
- case ets:lookup(?MONITOR_TABLE, Pid) of
- [] ->
+ ToAdd = [#client{dbname=DBN, pid=Pid} || DBN <- DbNames],
+ ets:insert(?REGISTRY_TABLE, ToAdd),
+ case ets:member(?MONITOR_TABLE, Pid) of
+ true ->
+ ok;
+ false ->
Ref = erlang:monitor(process, Pid),
- ets:insert(?MONITOR_TABLE, {Pid, Ref});
- [{Pid, _}] ->
- ok
+ ets:insert(?MONITOR_TABLE, {Pid, Ref})
end,
{reply, ok, St};
handle_call({unregister, Pid, DbNames}, _From, St) ->
+ % TODO: Check into a multi-pattern matchspec and the
+ % use of select_delete to see if that's faster.
lists:foreach(fun(DbName) ->
- unregister_pattern(#client{dbname=DbName, pid=Pid, _='_'})
+ ets:match_delete(?REGISTRY_TABLE, pattern(DbName, Pid))
end, DbNames),
+ maybe_drop_monitor(Pid),
{reply, ok, St};
handle_call({unregister_all, Pid}, _From, St) ->
- unregister_pattern(#client{pid=Pid, _='_'}),
+ ets:match_delete(?REGISTRY_TABLE, pattern(Pid)),
+ drop_monitor(Pid),
{reply, ok, St};
handle_call(Msg, From, St) ->
couch_log:notice("~s ignoring call ~w from ~w", [?MODULE, Msg, From]),
- {reply, ignored, St, 0}.
+ {reply, ignored, St}.
handle_cast(Msg, St) ->
couch_log:notice("~s ignoring cast ~w", [?MODULE, Msg]),
- {noreply, St, 0}.
+ {noreply, St}.
handle_info({'DOWN', _Ref, process, Pid, _Reason}, St) ->
- unregister_pattern(#client{pid=Pid, _='_'}),
- {noreply, St};
+ ets:match_delete(?REGISTRY_TABLE, pattern(Pid)),
+ ets:delete(?REGISTRY_TABLE, Pid),
+ {norepy, St};
handle_info(Msg, St) ->
couch_log:notice("~s ignoring info ~w", [?MODULE, Msg]),
- {noreply, St, 0}.
+ {noreply, St}.
code_change(_OldVsn, St, _Extra) ->
{ok, St}.
-unregister_pattern(Pattern) ->
- Clients = ets:match_object(?REGISTRY_TABLE, Pattern),
- Refs = lists:foldl(fun(#client{pid=Pid}=Cli, Acc) ->
- ets:delete_object(?REGISTRY_TABLE, Cli),
- case ets:lookup(?MONITOR_TABLE, Pid) of
- [{Pid, Ref}] ->
- ets:delete(?MONITOR_TABLE, Pid),
- [Ref | Acc];
- [] ->
- Acc
- end
- end, [], Clients),
- lists:foreach(fun(Ref) ->
- erlang:demonitor(Ref, [flush])
- end, Refs).
+maybe_drop_monitor(Pid) ->
+ case ets:select_count(?REGISTRY_TABLE, mspec(Pid)) of
+ 0 -> drop_monitor(Pid);
+ _ -> ok
+ end.
+
+
+drop_monitor(Pid) ->
+ case ets:lookup(?MONITOR_TABLE, Pid) of
+ [{Pid, Ref}] ->
+ ets:delete(?MONITOR_TABLE, Pid),
+ erlang:demonitor(Ref, [flush]);
+ [] ->
+ ok
+ end.
+
+
+-compile({inline, [
+ mspec/1,
+ pattern/1,
+ pattern/2
+]}).
+
+
+mspec(Pid) ->
+ [{pattern(Pid), [], ['$_']}].
+
+
+pattern(Pid) ->
+ #client{pid=Pid, _='_'}.
+
+
+pattern(DbName, Pid) ->
+ #client{dbname=DbName, pid=Pid, _='_'}.