diff options
author | Francesco Mazzoli <francesco@rabbitmq.com> | 2012-01-17 12:19:31 +0000 |
---|---|---|
committer | Francesco Mazzoli <francesco@rabbitmq.com> | 2012-01-17 12:19:31 +0000 |
commit | 065f57944a56b7d8183dfa04761247b5b760fdef (patch) | |
tree | e02ac8b53fe9b947306053118e56b148ff4f2a69 | |
parent | aea58d91b22163ee8cee76ce8d4b62224ebfa0e7 (diff) | |
download | rabbitmq-server-065f57944a56b7d8183dfa04761247b5b760fdef.tar.gz |
Split guid/0 in guid/0 and the faster fast_guid/0.
The first function works like the old one (hashes the {serial, counter} each
time.
The second function (fast_guid/0) hashes the serial once, and the XORs it with
the counter each time a new guid is needed. Thus, it is more predictable but
should not produce less unique guids.
If the fast function is used when generating ids for messages, it leads to a
considerable speedup when testing with BroadcastMain (from 67k msg/s to
75k msg/s).
-rw-r--r-- | src/rabbit_basic.erl | 2 | ||||
-rw-r--r-- | src/rabbit_guid.erl | 48 |
2 files changed, 37 insertions, 13 deletions
diff --git a/src/rabbit_basic.erl b/src/rabbit_basic.erl index b116821c..0af35134 100644 --- a/src/rabbit_basic.erl +++ b/src/rabbit_basic.erl @@ -139,7 +139,7 @@ message(XName, RoutingKey, #content{properties = Props} = DecodedContent) -> {ok, #basic_message{ exchange_name = XName, content = strip_header(DecodedContent, ?DELETED_HEADER), - id = rabbit_guid:guid(), + id = rabbit_guid:fast_guid(), is_persistent = is_message_persistent(DecodedContent), routing_keys = [RoutingKey | header_routes(Props#'P_basic'.headers)]}} diff --git a/src/rabbit_guid.erl b/src/rabbit_guid.erl index 2d0f5014..9a464139 100644 --- a/src/rabbit_guid.erl +++ b/src/rabbit_guid.erl @@ -19,7 +19,7 @@ -behaviour(gen_server). -export([start_link/0]). --export([guid/0, string_guid/1, binstring_guid/1]). +-export([guid/0, fast_guid/0, string_guid/1, binstring_guid/1]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -39,6 +39,7 @@ -spec(start_link/0 :: () -> rabbit_types:ok_pid_or_error()). -spec(guid/0 :: () -> guid()). +-spec(fast_guid/0 :: () -> guid()). -spec(string_guid/1 :: (any()) -> string()). -spec(binstring_guid/1 :: (any()) -> binary()). @@ -65,11 +66,9 @@ update_disk_serial() -> end, Serial. -%% generate a GUID. -%% -%% The id is only unique within a single cluster and as long as the -%% serial store hasn't been deleted. -guid() -> +%% Generate an un-hashed guid. To be used when one is hashed in the process +%% dictionary. +fresh_guid() -> %% We don't use erlang:now() here because a) it may return %% duplicates when the system clock has been rewound prior to a %% restart, or ids were generated at a high rate (which causes @@ -78,16 +77,41 @@ guid() -> %% %% A persisted serial number, the node, and a unique reference %% (per node incarnation) uniquely identifies a process in space - %% and time. We combine that with a process-local counter to give - %% us a GUID. - G = case get(guid) of - undefined -> Serial = gen_server:call(?SERVER, serial, infinity), - {{Serial, node(), make_ref()}, 0}; + %% and time. + Serial = gen_server:call(?SERVER, serial, infinity), + {Serial, node(), make_ref()}. + +%% generate a non-predictable GUID. +%% +%% The id is only unique within a single cluster and as long as the +%% serial store hasn't been deleted. +%% +%% If you are not concerned with predictability, fast_guid/0 is faster. +guid() -> + %% Here instead of hashing once we hash the GUID and the counter each time, + %% so that the GUID is not predictable. + G = case get(fast_guid) of + undefined -> {fresh_guid(), 0}; {S, I} -> {S, I+1} end, - put(guid, G), + put(fast_guid, G), erlang:md5(term_to_binary(G)). +%% generate a GUID. This function should be used when performance is a +%% priority and predictability is not an issue. +fast_guid() -> + %% We hash a fresh GUID and then XOR it with a process-local counter + %% to get a new GUID each time. + {S, I} = + case get(guid) of + undefined -> G = fresh_guid(), + <<S0:128/integer>> = erlang:md5(term_to_binary(G)), + {S0, 0}; + {S0, I0} -> {S0, I0+1} + end, + put(guid, {S, I}), + <<(S bxor I):128>>. + %% generate a readable string representation of a GUID. %% %% employs base64url encoding, which is safer in more contexts than |