Reputation: 1658
I am trying to generate unique values in c# with the help of DateTime ticks and and incrementing number. Pseudo code:
I ran the test for generating 2 million number and inserting in database column which has unique constraint set and it ran successfully.
Here is the piece of code that does that:
private static long _sequence = 1;
public static long GetUniqueNumber()
{
const int timeShift = 21;
var dateTime = DateTime.Now.Ticks;
const long dateTimeMask = ~(0L) >> timeShift;
const long sequenceMask = ((~(0L) >> (64 - timeShift)));
var seq = Interlocked.Increment(ref _sequence);
var dateTimeNo = (dateTimeMask & dateTime) << timeShift;
var seqNum = (seq & sequenceMask);
var num = dateTimeNo | seqNum;
return num;
}
I have two questions: 1. Is this logic good enough to generate unique numbers ? 2. I find that some generated numbers are '-ve' which I didn't understand.
Any help/suggestions/improvements are welcome.
Upvotes: 0
Views: 1151
Reputation: 860
Negative numbers are due to implementation of long. As it is a signed number, if MSB that is bit 64 becomes '1' after the bit wise manipulation, the number will become negative. Nothing to worry about that.
Upvotes: 0
Reputation: 1502286
Is this logic good enough to generate unique numbers
Unique across what scope? Across multiple computers/processes/AppDomain
s?, certainly not. Within a single AppDomain
? Not really. Generating 2 million numbers is irrelevant - that's just testing that your sequence part works. (221 is just over 2 million.)
If you can call GetUniqueNumber
221+1 times within the granularity of DateTime.Now
(which is likely to be ~10-15ms) then you'll get a repeat. Have you measured how fast your computed can call this?
Then there's the fact that those 43 bits will be repeated in 243 ticks' time... or at least would be if you had a sufficiently fine-grained clock. (And sooner or later the granularity will work against you.)
I find that some generated numbers are '-ve' which I didn't understand.
Whenever dateTimeNo
has its top bit (out of 43) set, you'll end up with a long
with the top bit set - which means it'll be negative.
EDIT: Also note that your shifting is broken. This:
const long dateTimeMask = ~(0L) >> timeShift;
is performed a sign-extended shift - so you're just ending up with ~0L.
In short: use Guid.NewGuid
. It's what it's there for.
Upvotes: 6