我想证明一个GUID在一个简单的测试程序中不是唯一的。
我原以为下面的代码会运行几个小时,但它不起作用。我该怎么做呢?
BigInteger begin = new BigInteger((long)0);
BigInteger end = new BigInteger("340282366920938463463374607431768211456",10); //2^128
for(begin; begin<end; begin++)
Console.WriteLine(System.Guid.NewGuid().ToString());
我用的是c#。
当然guid也会发生碰撞。由于guid是128位的,只需生成其中的2^128 + 1个,根据鸽子洞原理,肯定会有碰撞。
但是当我们说一个GUID是唯一的时,我们真正的意思是键空间非常大,实际上不可能意外地生成两次相同的GUID(假设我们是随机生成GUID)。
如果随机生成n个guid序列,那么至少发生一次碰撞的概率大约是p(n) = 1 - exp(-n^2 / 2 * 2^128)(这是一个生日问题,可能的生日数量为2^128)。
n p(n)
2^30 1.69e-21
2^40 1.77e-15
2^50 1.86e-10
2^60 1.95e-03
为了使这些数字具体化,2^60 = 1.15e+18。所以,如果你每秒生成10亿个guid,你将需要36年才能生成2^60个随机guid,即使这样,你发生碰撞的概率仍然是1.95e-03。在接下来的36年里,你更有可能在生命中的某个时刻被谋杀(4.76e-03),而不是发现一次碰撞。祝你好运。
Kai,我提供了一个程序,将做什么你想使用线程。它是根据以下条款授权的:您必须向我支付每小时每CPU内核0.0001美元的费用。费用在每个日历月的月底支付。请联系我的贝宝账户详细信息在您最早的方便。
using System;
using System.Collections.Generic;
using System.Linq;
namespace GuidCollisionDetector
{
class Program
{
static void Main(string[] args)
{
//var reserveSomeRam = new byte[1024 * 1024 * 100]; // This indeed has no effect.
Console.WriteLine("{0:u} - Building a bigHeapOGuids.", DateTime.Now);
// Fill up memory with guids.
var bigHeapOGuids = new HashSet<Guid>();
try
{
do
{
bigHeapOGuids.Add(Guid.NewGuid());
} while (true);
}
catch (OutOfMemoryException)
{
// Release the ram we allocated up front.
// Actually, these are pointless too.
//GC.KeepAlive(reserveSomeRam);
//GC.Collect();
}
Console.WriteLine("{0:u} - Built bigHeapOGuids, contains {1} of them.", DateTime.Now, bigHeapOGuids.LongCount());
// Spool up some threads to keep checking if there's a match.
// Keep running until the heat death of the universe.
for (long k = 0; k < Int64.MaxValue; k++)
{
for (long j = 0; j < Int64.MaxValue; j++)
{
Console.WriteLine("{0:u} - Looking for collisions with {1} thread(s)....", DateTime.Now, Environment.ProcessorCount);
System.Threading.Tasks.Parallel.For(0, Int32.MaxValue, (i) =>
{
if (bigHeapOGuids.Contains(Guid.NewGuid()))
throw new ApplicationException("Guids collided! Oh my gosh!");
}
);
Console.WriteLine("{0:u} - That was another {1} attempts without a collision.", DateTime.Now, ((long)Int32.MaxValue) * Environment.ProcessorCount);
}
}
Console.WriteLine("Umm... why hasn't the universe ended yet?");
}
}
}
PS:我想试试并行扩展库。这很简单。
使用OutOfMemoryException作为控制流感觉是错误的。
EDIT
看来这还能吸引选票。所以我已经修复了GC.KeepAlive()问题。并将其更改为与c# 4一起运行。
澄清一下我的支持条款:支持只在2010年2月28日有效。请使用时间机器仅在当天提出支持请求。
编辑2
与往常一样,GC在管理内存方面比我做得更好;以前我自己做这件事的任何尝试都注定要失败。