[c#] GUID가 고유하지 않다는 간단한 증거

간단한 테스트 프로그램에서 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 #을 사용하고 있습니다.



답변

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?");
        }
    }
}

추신 : 병렬 확장 라이브러리를 사용 해보고 싶었습니다. 그것은 쉽다.

제어 흐름으로 OutOfMemoryException을 사용하면 느낌이 잘못됩니다.

편집하다

글쎄, 이것은 여전히 ​​투표를 유치하는 것 같습니다. 그래서 GC.KeepAlive () 문제를 해결했습니다. 그리고 C # 4로 실행되도록 변경했습니다.

또한 지원 조건을 명확히하기 위해 2010 년 2 월 28 일만 지원됩니다. 그날에만 지원 요청을하려면 타임머신을 사용하십시오.

편집 2
항상 그렇듯이 GC는 메모리 관리보다 더 나은 작업을 수행합니다. 직접 시도했던 모든 시도는 실패로 끝났습니다.


답변

이것은 몇 시간 이상 동안 실행될 것입니다. 그것이 1GHz에서 반복된다고 가정하면 (그것은 그것보다 훨씬 느리지 않을 것입니다), 그것은 10790283070806014188970 년 동안 실행될 것입니다. 우주보다 나이가 약 83 억 배나 더 깁니다.

가정 무어의 법칙은 은,이 프로그램을 실행 수백 년을 기다려야 빠른 시간 수십억하는 컴퓨터에서 실행하지에 많이 더 빨리 될 것이다 보유하고있다. 실제로 CPU 속도가 두 배 (약 18 개월)로 걸리는 것보다 실행 시간이 오래 걸리는 프로그램은 CPU 속도가 증가 할 때까지 기다렸다가 실행하기 전에 새 CPU를 구입하면 (작성하지 않는 한) 더 빨리 완료됩니다. 새 하드웨어에서 일시 중지했다가 다시 시작할 수 있습니다).


답변

GUID는 이론적으로 고유하지 않습니다. 증거는 다음과 같습니다.

  • GUID는 128 비트 숫자입니다.
  • 오래된 GUID를 재사용하지 않으면 2 ^ 128 + 1 이상의 GUID를 생성 할 수 없습니다

그러나 태양의 전체 전력 출력이이 작업을 수행하도록 지시 된 경우 완료되기 오래 전에 냉각 될 것입니다.

GUID는 여러 가지 다른 전술을 사용하여 생성 될 수 있으며,이 중 일부는 특정 시스템이 동일한 GUID를 두 번 생성하지 않도록 특별한 조치를 취합니다. 특정 알고리즘에서 충돌을 발견하면 GUID를 생성하는 특정 방법이 나쁘다는 것을 알 수 있지만 일반적으로 GUID에 대해서는 아무 것도 증명하지 못합니다.


답변

물론 GUID가 충돌 할 수 있습니다. GUID는 128 비트이므로 2^128 + 1이를 생성 하고 비둘기 구멍 원리에 따라 충돌이 발생해야합니다.

그러나 GUID가 고유하다고 말할 때 실제로 의미하는 것은 키 공간이 너무 커서 실수로 동일한 GUID를 두 번 생성하는 것이 실제로 불가능하다는 것입니다 (GUID를 임의로 생성한다고 가정).

일련의 nGUID를 무작위로 생성하는 경우 , 최소한 하나의 충돌 가능성은 대략적인 것입니다 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를 생성하는 경우 2^60임의의 GUID 를 생성하는 데 36 년이 걸리며 충돌 가능성은 여전히 ​​큽니다 1.95e-03. 앞으로 36 년 동안 충돌을 발견하는 것보다 인생의 어느 시점 ( 4.76e-03) 에서 살해 될 가능성이 높습니다 . 행운을 빕니다.


답변

고유성이 걱정되는 경우 항상 새 GUID를 구매하여 기존 GUID를 버릴 수 있습니다. 원한다면 eBay에 올려 놓겠습니다.


답변

개인적으로, “빅뱅”은 두 GUID가 충돌했을 때 발생했다고 생각합니다.


답변

양자 bogosort 알고리즘 의 변형으로 O (1) 시간에이를 표시 할 수 있습니다 .

Guid g1 = Guid.NewGuid();
Guid g2 = Guid.NewGuid();
if(g1 != g2) Universe.Current.Destroy();