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, _='_'}.