summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Mazzoli <francesco@rabbitmq.com>2012-01-17 12:19:31 +0000
committerFrancesco Mazzoli <francesco@rabbitmq.com>2012-01-17 12:19:31 +0000
commit065f57944a56b7d8183dfa04761247b5b760fdef (patch)
treee02ac8b53fe9b947306053118e56b148ff4f2a69
parentaea58d91b22163ee8cee76ce8d4b62224ebfa0e7 (diff)
downloadrabbitmq-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.erl2
-rw-r--r--src/rabbit_guid.erl48
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