Prosty dowód, że GUID nie jest unikalny [zamknięty]


323

Chciałbym udowodnić, że GUID nie jest unikalny w prostym programie testowym. Spodziewałem się, że poniższy kod będzie działał przez wiele godzin, ale nie działa. Jak mogę to zrobić?

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());

Używam C #.


107
Jako programista, co byś powiedział, gdyby użytkownik przyszedł do Ciebie i powiedział „nie działa”?
JoshJordan,

152
Poczekaj kilka bilionów lat.
hobbs

67
Zmodernizowany, ponieważ jest to najbardziej zabawna rzecz, jaką widziałem dzisiaj w Internecie.
jrockway,

32
@jrockway - lol. Mam problem ze znalezieniem czegoś na temat tego pytania, które nie jest zasadniczo błędne. Im dłużej na to patrzę, tym zabawniej robi się.
tylerl

243
Jest tylko globalnie wyjątkowy, więc jest wyjątkowy tylko na naszej planecie. Jeśli chcesz naprawdę unikalnego identyfikatora, musisz użyć uniwersalnie unikalnego identyfikatora (UUID). Zakładam, że interesuje Cię tylko wyjątkowość w naszym wszechświecie. :-)
tvanfosson,

Odpowiedzi:


407

Kai, dostarczyłem program, który zrobi to, co chcesz, używając wątków. Jest licencjonowany na następujących warunkach: musisz zapłacić mi 0,0001 $ za godzinę za rdzeń procesora, na którym go uruchomisz. Opłaty są płatne na koniec każdego miesiąca kalendarzowego. Proszę o kontakt w celu uzyskania szczegółów mojego konta PayPal w najbliższym dogodnym terminie.

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: Chciałem wypróbować bibliotekę rozszerzeń Parallel. To było łatwe.

A użycie OutOfMemoryException jako przepływu sterowania jest po prostu błędne.

EDYTOWAĆ

Wygląda na to, że wciąż przyciąga głosy. Naprawiłem więc problem GC.KeepAlive (). I zmieniłem, aby działał z C # 4.

Aby wyjaśnić warunki mojego wsparcia: wsparcie jest dostępne tylko 28 lutego 2010 r. Skorzystaj z wehikułu czasu, aby wysyłać prośby o wsparcie tylko tego dnia.

EDYCJA 2 Jak zawsze, GC wykonuje lepszą pracę niż ja w zarządzaniu pamięcią; wszelkie wcześniejsze próby samodzielnego zrobienia tego były skazane na niepowodzenie.


120
Ta ostatnia konsola. WriteLine bardzo mnie rozśmieszyła. Myślę, że CommonlyAcceptedCosmologicTheoriesWrongExceptionzamiast tego powinieneś rzucić .
R. Martinho Fernandes,

17
czy oznaczenie tego jako zaakceptowanego oznacza również, że @Kai akceptuje warunki określone przez @ligos?
kb.

3
Ustawienie reserveSomeRam = null;tak naprawdę niczego nie osiąga.
DevinB

4
@devinb proszę wyjaśnić? wygląda na to, że zwalnia bajty, które zostały wcześniej przydzielone, aby GC mógł Collect()to zrobić. Dlaczego nic nie osiąga?
mythz

3
GuidCollisionDetector. Nazwa ma potencjał
Ufuk Hacıoğulları

226

To potrwa znacznie dłużej niż godziny. Zakładając, że pętle będą działały z częstotliwością 1 GHz (co nie będzie - będzie znacznie wolniejsze), będzie działać przez 10790283070806014188970 lat. Co jest około 83 miliardów razy dłuższe niż wiek wszechświata.

Zakładając, że obowiązuje prawo Moores , znacznie szybciej byłoby nie uruchamiać tego programu, czekać kilkaset lat i uruchamiać go na komputerze, który jest miliardy razy szybszy. W rzeczywistości każdy program, którego uruchomienie zajmuje więcej czasu niż wymaga podwojenia szybkości procesora (około 18 miesięcy), zakończy się wcześniej, jeśli poczekasz, aż zwiększy się szybkość procesora i kupisz nowy procesor przed uruchomieniem (chyba że napiszesz go tak, aby można zawiesić i wznowić na nowym sprzęcie).


27
cholera - więc może serwerowe wątki generujące przewodniki to lepszy pomysł?
Kai

107
4 wątki na czterordzeniowym procesorze sprawiłyby, że działałby 20 miliardów razy w stosunku do wieku wszechświata - więc tak, to bardzo by pomogło.
rjmunro

34
Podejrzewam, że to troll, ale niestety nie jest tak: nici nie są magiczne. Jeśli możesz wykonać miliard operacji na sekundę w jednym wątku, to przejście do dziesięciu wątków oznacza, że ​​każdy z nich wykonuje 1/10 tak często. Każdy wątek wykonuje 100 M operacji na sekundę; całkowita liczba operacji na sekundę nie jest zwiększana. Sposobem na zwiększenie liczby operacji na sekundę jest zakup większej liczby komputerów. Załóżmy, że kupiłeś miliard więcej komputerów. Zmniejszyłoby to problem do zaledwie 10790283070806 lat, co wciąż trwa dłużej niż cztery godziny.
Eric Lippert,

10
Myślę, że rjmunro zakłada, że ​​każdy wątek będzie działał na osobnym rdzeniu; 83 miliardy wszechświatów / 4 rdzenie rzeczywiście w przybliżeniu równa się 20 miliardom wszechświatów. Czas na zakup akcji Intela!
Dour High Arch

4
@Erik 83 miliardy procesorów oznacza, że ​​będziesz w stanie to zrobić w czasie, w jakim wszechświat istniał do tej pory. Nawet to nie wystarczy.
rjmunro,

170

GUID jest teoretycznie nieunikalny. Oto twój dowód:

  • GUID to 128-bitowa liczba
  • Nie można wygenerować 2 ^ 128 + 1 lub więcej identyfikatorów GUID bez ponownego użycia starych identyfikatorów GUID

Gdyby jednak cała moc wyjściowa słońca była skierowana na wykonanie tego zadania, na długo przed jego zakończeniem stałoby się zimno.

Identyfikatory GUID można generować przy użyciu wielu różnych taktyk, z których niektóre podejmują specjalne środki, aby zagwarantować, że dana maszyna nie wygeneruje dwukrotnie tego samego identyfikatora GUID. Znalezienie kolizji w konkretnym algorytmie pokazałoby, że twoja metoda generowania identyfikatorów GUID jest zła, ale nie udowodniłaby niczego w ogóle o identyfikatorach GUID.


44
Zasada Pigeonhole na ratunek!
yfeldblum,

22
+1 za zachodzące słońce, komentarz zimny. Był gdzieś interesujący komentarz na temat bezcelowości kluczy szyfrujących> 256 bitów. Wykonanie iteracji wszystkich możliwych kluczowych wartości wymagałoby więcej energii niż utrzymuje cały wszechświat. Włączenie odrobiny w CPU wymaga niewielkiej ilości energii (to ona generuje ciepło), która po pomnożeniu 2 ^ 256 razy jest naprawdę ogromną liczbą przekraczającą energię zgromadzoną we wszechświecie, używając E = mc2 wszechświat potrzebowałby masy 2 ^ 227 kg, nasze słońce ma 2 ^ 101 kg, czyli 2 ^ 126 słońc!
Skizz,

31
@Skizz: Dotyczy to tylko ataków siłowych. Gdy schemat szyfrowania jest „zepsuty”, oznacza to, że można go rozwiązać w krótszym czasie niż brutalna siła, ale czas rozwiązania pozostaje proporcjonalny do wielkości klucza.
Steven Sudit

1
@StevenSudit: proporcjonalny do wykładnika wielkości klucza (chyba że P == NP)
Ihar Bury

1
@Orlangur Proporcjonalny do wielkości klucza mierzonego w bitach.
Steven Sudit,

137

Oczywiście identyfikatory GUID mogą się kolidować. Ponieważ identyfikatory GUID są 128-bitowe, wystarczy 2^128 + 1je wygenerować zgodnie z zasadą szufladki musi dojść do kolizji.

Ale kiedy mówimy, że GUID jest unikalny, to tak naprawdę mamy na myśli to, że przestrzeń klucza jest tak duża, że ​​praktycznie niemożliwe jest przypadkowe wygenerowanie tego samego GUID dwukrotnie (zakładając, że generujemy GUID losowo).

Jeśli nlosowo generujesz sekwencję identyfikatorów GUID, prawdopodobieństwo co najmniej jednej kolizji jest w przybliżeniu p(n) = 1 - exp(-n^2 / 2 * 2^128)(jest to problem urodzinowy z liczbą możliwych urodzin 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

Aby te numery betonu 2^60 = 1.15e+18. Jeśli więc wygenerujesz miliard GUID na sekundę, wygenerowanie 2^60losowych GUID zajmie ci 36 lat, a nawet prawdopodobieństwo kolizji jest nadal 1.95e-03. Bardziej prawdopodobne jest, że w pewnym momencie życia zostaniesz zamordowany ( 4.76e-03) niż podczas kolizji w ciągu następnych 36 lat. Powodzenia.


239
Jeśli zostaniesz zamordowany w pewnym momencie swojego życia, są szanse, że to się skończy.
Michael Myers

25
@mmyers: Doskonały punkt. Oznacza to, że moje szanse na zabójstwo są teraz absurdalnie niskie, ponieważ to nie koniec mojego życia. Och, czekaj ...
Steven Sudit

Ponadto, jeśli dwa identyfikatory GUID zostaną utworzone w krótkim czasie, szanse na ich użycie w tym samym systemie są niewielkie. Dlatego zwiększa to wyjątkowość.
AMissico,

Te liczby i odniesienie do problemu urodzin są bez znaczenia. Algorytmy generowania GUID nie generują wartości w całym zakresie z jednakowym prawdopodobieństwem. W rzeczywistości IIRC oryginalny algorytm wykorzystał adres MAC generującego komputera + aktualny czas jako część wyniku - co zmniejsza ryzyko kolizji z prowadnicami generowanymi na innych komputerach, ale oczywiście zmniejsza przestrzeń klucza.
Joe

17
Zakładasz, że prawdopodobieństwo zamordowania jest stałe dla wszystkich ludzi. Ale najwyraźniej ludzie, którzy piszą złośliwe uwagi na postach na forum, są ludźmi, których prawdopodobieństwo zamordowania jest większe niż przeciętnej osoby.
Jay

61

Jeśli martwisz się o wyjątkowość, zawsze możesz kupić nowe identyfikatory GUID, aby wyrzucić stare. Jeśli chcesz, wystawię trochę na eBayu.


13
Fajnie - ile kosztuje cały zestaw, od 0 do (2 ^ 128) -1?
Steve314,

23
W sprzedaży 0,01 USD za 1 tys. GUID. Wrzucę bambusowe kuranty wiatrowe, jeśli zamówisz w ciągu następnych 60 minut.
ctacke

7
Mój zestaw jest bardziej ekskluzywny i wyższej jakości. Są dwukrotnie sprawdzane i weryfikowane, co sprawia, że ​​są warte 1 USD za identyfikator GUID. Możesz nawet kupić je partiami, jeśli nie chcesz w pełni zainwestować za jednym razem. Będę musiał jednak naliczyć dodatkowe 10 USD za partię.
Thomas

3
Ustawię cię na abonament miesięczny i dam ci nieograniczoną liczbę przewodników za odpowiednią cenę. ^ Ci faceci próbują cię oszukać i sprzedać ci drogie przewodniki. Sprzedam ci wysokiej jakości przewodniki wykonane w Chinach!
ErocM,

47

Osobiście uważam, że „Wielki Wybuch” został spowodowany, gdy zderzyły się dwa identyfikatory GUID.


4
Pamiętaj tylko, że potrzeba do tego specjalnego programisty ...
AnthonyLambert

Chciałbym usłyszeć twoje uzasadnienie swojej teorii. Myślę, że moglibyśmy założyć nową religię w oparciu o to i zrekrutować T.Cruise!
ErocM,

@ErocM; Zobacz „Brane cosmology” ( en.wikipedia.org/wiki/Brane_cosmology ) i „Membrane (M-Theory)” ( en.wikipedia.org/wiki/Membrane_(M- Theory ) ). Chodzi o to, że jeśli dwie branże się stykają, powstaje nowy wszechświat. Dlatego możesz wnioskować, że jeśli dotkną się dwa identyfikatory GUID, powstaje nowy wszechświat.
AMissico,

2
Jeśli Timecop nas czegoś nauczył, to ta sama materia nie może zajmować tej samej przestrzeni w danym momencie. Gdyby więc dwa GUID-y zderzyły się, pochłonęłyby się nawzajem, a powstała implozja wygenerowałaby czarną dziurę, pochłaniającą cały wszechświat. Tak więc w rzeczywistości nie stworzyłby Wszechświata, zniszczy go.
AJC

42

Możesz to pokazać w czasie O (1) za pomocą wariantu kwantowego algorytmu Bogosort .

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

21
Dostaję wyjątek podczas wywoływania Destroy (). Na podstawie tekstu sądzę, że w moim komputerze brakuje sprzętu niezbędnego do zniszczenia obecnego wszechświata. Czy wiesz, gdzie mogę to uzyskać?
Steven Sudit

11
@Steven: Nie, niektórzy menadżerowie zbytnio martwili się tym, jak zły byłby ten interfejs API dla opinii publicznej, i podyktowali, że zawsze zawodzi ze „względów bezpieczeństwa”. Jeśli spojrzeć na źródła danej metody jest nie tylko, że jedna linia: throw new MundaneHardwareException();. W każdym razie, słyszałem, że chłopaki z CERN mają coś w rodzaju Big Hadron Thingy, który może załatwić sprawę ...
R. Martinho Fernandes

7
@Martinho: Ach, ok. Zajrzę do zastąpienia Universe.Current.Destroy()z Cern.Lhc.DestroyThisUniverse().
Steven Sudit,

61
Wiedziałem, że istnieje powód, dla którego programowałem w Haskell. Te działania niepożądane stają się przerażające.
Edward KMETT

6
„Istnieje teoria, która mówi, że jeśli ktokolwiek kiedykolwiek odkryje dokładnie, do czego służy Wszechświat i dlaczego tu jest, natychmiast zniknie i zostanie zastąpiony czymś jeszcze dziwniej niewytłumaczalnym. Istnieje inna teoria, która mówi, że tak się już stało. . ” - Douglas Adams, Przewodnik autostopowicza po galaktyce
Mike Pirnat

28

Wszelkie dwa identyfikatory GUID są bardzo unikalne (nie równe).

Zobacz ten wpis SO oraz z Wikipedii

Chociaż nie ma gwarancji, że każdy wygenerowany identyfikator GUID będzie unikalny, całkowita liczba unikalnych kluczy (2 ^ 128 lub 3,4 × 10 ^ 38) jest tak duża, że ​​prawdopodobieństwo dwukrotnego wygenerowania tej samej liczby jest bardzo małe. Rozważmy na przykład obserwowalny wszechświat, który zawiera około 5 × 10 ^ 22 gwiazd; każda gwiazda mogłaby wtedy mieć 6,8 × 10 ^ 15 uniwersalnie unikalnych GUID.

Prawdopodobnie więc musisz poczekać jeszcze wiele miliardów lat i mieć nadzieję, że trafisz na jeden przed wszechświatem, ponieważ wiemy, że dobiega końca.


więc 2 ^ 128 to nieprawidłowa liczba możliwych prowadnic?
Kai

21
To jest. Jak myślisz, dlaczego 2 ^ 128 to mała liczba?
jrockway,

Tak, 2 ^ 128 to poprawna liczba możliwych prowadnic.
Graviton,

3
To piekło z liczby. $ irb >> 2**128 => 340282366920938463463374607431768211456
adamJLev

45
@Infinity - Nawet tobie?
Austin Richardson

27

[Aktualizacja:] Jak zauważają poniższe komentarze, nowsze identyfikatory GUID MS to V4 i nie używają adresu MAC jako części generowania GUID (nie widziałem jednak żadnych oznak implementacji V5 z MS, więc jeśli ktoś ma link potwierdzający, że daj mi znać). Jednak w wersji V4 czas jest nadal istotny, a szanse na powielanie identyfikatorów GUID pozostają tak małe, że nie mają znaczenia dla żadnego praktycznego zastosowania. Z pewnością nigdy nie będzie możliwe wygenerowanie zduplikowanego identyfikatora GUID na podstawie pojedynczego testu systemu, takiego jak OP.

W większości tych odpowiedzi brakuje jednego istotnego punktu na temat implementacji GUID Microsoftu. Pierwsza część identyfikatora GUID oparta jest na znaczniku czasu, a inna część oparta jest na adresie MAC karty sieciowej (lub liczbie losowej, jeśli nie jest zainstalowana karta sieciowa).

Jeśli dobrze to rozumiem, oznacza to, że jedynym niezawodnym sposobem na zduplikowanie identyfikatora GUID byłoby uruchomienie jednoczesnych generacji identyfikatorów GUID na wielu komputerach, na których adresy MAC były takie same ORAZ i gdzie zegary w obu systemach były w tym samym czasie, co generacja wystąpił (znacznik czasu jest oparty na milisekundach, jeśli dobrze to rozumiem) ... nawet wtedy jest wiele innych bitów w liczbie losowej, więc szanse są nadal znikome.

Dla wszystkich praktycznych celów identyfikatory GUID są uniwersalne.

Całkiem dobry opis MS GUID znajduje się na blogu „The Old New Thing”


3
Jest to faktycznie wykonalne podczas korzystania z wirtualizacji. Możesz i dostajesz duplikaty prowadnic.
Goran,

8
Raymond jest jednak przestarzały w części Adres MAC, Microsoft już z nich nie korzysta. Zobacz en.wikipedia.org/wiki/GUID#Al Algorytm, aby zobaczyć różnicę między przewodnikami V1 i V4.
Michael Stum

1
Tak już nie jest. Obecny schemat V5 to zaledwie 128 bitów czystej dobroci pseudolosowej.
Edward KMETT

zabawne, jak podajesz wszystko, co zrobiłem miesiąc później ode mnie, a ty dostajesz 16 punktów, a ja wciąż mam 0?
AnthonyLambert

1
Tak Tony, jest w tym coś dziwnego. Kiedy odpowiadałem na post, były tylko 3 lub 4 odpowiedzi i nie pamiętałem, że widziałem twoją ... gdybym to zrobił, po prostu oceniłbym to. Zazwyczaj nie odpowiadam na pytania, gdy są już inne odpowiedzi, które obejmują je wystarczająco dobrze (dlatego prawdopodobnie mam raczej niską ogólną liczbę przedstawicieli).
Stephen M. Redd

23

Oto fajna mała metoda rozszerzenia, której możesz użyć, jeśli chcesz sprawdzić unikalność guid w wielu miejscach kodu.

internal static class GuidExt
{
    public static bool IsUnique(this Guid guid)
    {
        while (guid != Guid.NewGuid())
        { }
        return false;
    }
}

Aby to nazwać, po prostu zadzwoń do Guid.IsUnique za każdym razem, gdy wygenerujesz nowy przewodnik ...

Guid g = Guid.NewGuid();
if (!g.IsUnique())
{
    throw new GuidIsNotUniqueException();
}

... cholera, nawet poleciłbym zadzwonić do niego dwa razy, aby upewnić się, że wszystko poszło dobrze w pierwszej rundzie.


2
Jak to zapewnia, że this guidnigdy nie został wygenerowany nigdzie indziej na tym świecie? : p Heck potrzebujemy pula światowych przewodników. :)
nawfal

19

Licząc do 2 ^ 128 - ambitny.

Wyobraźmy sobie, że możemy policzyć 2 ^ 32 identyfikatory na sekundę na maszynę - nie to ambitne, ponieważ nie jest to nawet 4,3 miliarda na sekundę. Przeznaczmy do tego zadania 2 ^ 32 maszyny. Ponadto, weźmy 2 ^ 32 cywilizacje na każdą przeznaczoną na zadanie te same zasoby.

Do tej pory możemy liczyć 2 ^ 96 identyfikatorów na sekundę, co oznacza, że ​​będziemy liczyć przez 2 ^ 32 sekundy (nieco ponad 136 lat).

Teraz potrzebujemy tylko 4 294 967 296 cywilizacji na każdą dedykowaną 4 294 967 296 maszyn, z których każda może zliczać 4 294 967 296 identyfikatorów na sekundę, wyłącznie do tego zadania przez następne około 136 lat - sugeruję, abyśmy teraz rozpoczęli to istotne zadanie; -)


17

Cóż, jeśli czas działania wynoszący 83 miliardy lat cię nie przeraża, pomyśl, że będziesz musiał także przechowywać wygenerowane identyfikatory GUID w celu sprawdzenia, czy masz duplikat; przechowywanie 2 ^ 128 16-bajtowych numerów wymagałoby tylko przydzielenia 4951760157141521099596496896 terabajtów pamięci RAM z góry, więc wyobrażając sobie, że masz komputer, który może to wszystko zmieścić i że w jakiś sposób znajdziesz miejsce, aby kupić moduły DIMM terabajta po 10 gramów każdy, łącznie ważą ponad 8 mas Ziemi, więc możesz poważnie przesunąć ją poza bieżącą orbitę, zanim jeszcze naciśniesz „Run”. Pomyśl dwa razy!


12
for(begin; begin<end; begin)
    Console.WriteLine(System.Guid.NewGuid().ToString());

Nie zwiększasz, beginwięc warunek begin < endjest zawsze spełniony.


1
nie - bo nie mogę iterować biginta
Kai

3
Czy to naprawdę ważne, że zapętla się wiecznie, a nie zapętla 340282366920938463463374607431768211456 razy?
Jay

3
więc ... wolałbyś zostać uderzony 340282366920938463463374607431768211456 razy czy na zawsze!?!?!?
ErocM,

tak naprawdę to właśnie odpowiada na pytanie! i brak głosów: p
nawfal


9

Przypuszczalnie masz powody, by sądzić, że algorytm do generowania prowadnic nie generuje liczb naprawdę losowych, ale w rzeczywistości cyklicznie z okresem << 2 ^ 128.

np. metoda RFC4122 używana do uzyskania identyfikatorów GUID, która naprawia wartości niektórych bitów.

Dowód jazdy na rowerze będzie zależeć od możliwej wielkości okresu.

W przypadku krótkich okresów podejściem może być tabela skrótów (GUID) -> GUID z wymianą w przypadku kolizji, jeśli identyfikatory GUID nie pasują (zakończ, jeśli tak się dzieje). Zastanów się również nad zrobieniem wymiany tylko w przypadkowym ułamku czasu.

Ostatecznie, jeśli maksymalny okres między kolizjami jest wystarczająco duży (i nie jest znany z góry), każda metoda da jedynie prawdopodobieństwo, że kolizja zostanie znaleziona, gdyby istniała.

Pamiętaj, że jeśli metoda generowania prowadnic jest oparta na zegarze (patrz RFC), może nie być możliwe ustalenie, czy występują kolizje, ponieważ albo (a) nie będziesz w stanie czekać wystarczająco długo, aby zegar się zawinął, lub (b) nie możesz poprosić o wystarczającą liczbę prowadnic w ciągu tyknięcia zegara, aby wymusić kolizję.

Alternatywnie możesz być w stanie pokazać statystyczną zależność między bitami w Guid lub korelację bitów między Guidami. Taki związek może sprawić, że wysoce prawdopodobne jest, że algorytm jest wadliwy, niekoniecznie będąc w stanie znaleźć rzeczywistą kolizję.

Oczywiście, jeśli chcesz tylko udowodnić, że Guids mogą się zderzyć, odpowiedzią jest matematyczny dowód, a nie program.


8

Nie rozumiem, dlaczego nikt nie wspominał o modernizacji karty graficznej ... Z pewnością, jeśli masz wysokiej klasy NVIDIA Quadro FX 4800 lub coś takiego (192 rdzenie CUDA), to pójdzie szybciej ...

Oczywiście, gdybyś mógł sobie pozwolić na kilka kart NVIDIA Qadro Plex 2200 S4 (przy 960 rdzeniach CUDA każdy), to obliczenia naprawdę by się krzyknęły . Być może NVIDIA byłaby skłonna pożyczyć ci kilka za „demonstrację technologii” jako wyczyn PR?

Z pewnością chcieliby wziąć udział w tych historycznych obliczeniach ...


hmmmm ... Mógłbym uruchomić go na naszej sieci 10 000 węzłów w pracy.
AnthonyLambert,

8

Ale czy musisz mieć pewność, że masz duplikat, czy dbasz tylko o to, czy może istnieć duplikat. Aby mieć pewność, że masz dwie osoby na te same urodziny, potrzebujesz 366 osób (nie licząc roku przestępnego). Aby mieć więcej niż 50% szans na posiadanie dwóch osób w te same urodziny, potrzebujesz tylko 23 osób. To jest problem urodzinowy .

Jeśli masz 32 bity, potrzebujesz tylko 77 163 wartości, aby mieć więcej niż 50% szans na duplikat. Wypróbuj to:

Random baseRandom = new Random(0);

int DuplicateIntegerTest(int interations)
{
    Random r = new Random(baseRandom.Next());
    int[] ints = new int[interations];
    for (int i = 0; i < ints.Length; i++)
    {
        ints[i] = r.Next();
    }
    Array.Sort(ints);
    for (int i = 1; i < ints.Length; i++)
    {
        if (ints[i] == ints[i - 1])
            return 1;
    }
    return 0;
}

void DoTest()
{
    baseRandom = new Random(0);
    int count = 0;
    int duplicates = 0;
    for (int i = 0; i < 1000; i++)
    {
        count++;
        duplicates += DuplicateIntegerTest(77163);
    }
    Console.WriteLine("{0} iterations had {1} with duplicates", count, duplicates);
}

1000 iterations had 737 with duplicates

Teraz 128 bitów to dużo, więc wciąż rozmawiasz z dużą liczbą przedmiotów, co daje małą szansę na kolizję. Potrzebujesz przybliżonej liczby rekordów dla danych kursów, stosując przybliżenie:

  • 0,8 miliarda miliardów na 1/1000 szansy na kolizję
  • 21,7 miliarda miliardów na 50% szansy na kolizję
  • 39,6 miliarda miliardów dla 90% szansy na kolizję

Każdego roku wysyłanych jest około 1E14 e-maili, więc na tym poziomie byłoby około 400 000 lat, zanim miałbyś 90% szans na posiadanie dwóch z tym samym GUID, ale to znacznie różni się od mówienia, że ​​musisz uruchomić komputer 83 miliardy razy wiek wszechświata lub że słońce ostygnie, zanim znajdzie duplikat.


7

Czy wszyscy nie tracicie ważnego punktu?

Myślałem, że identyfikatory GUID zostały wygenerowane przy użyciu dwóch rzeczy, które sprawiają, że szanse na ich unikalność na skalę globalną są dość wysokie. Po pierwsze, są one zapełnione adresem MAC komputera, na którym jesteś, a dwa wykorzystują czas, w którym zostały wygenerowane, oraz liczbę losową.

Więc jeśli nie uruchomisz go na rzeczywistej maszynie i nie wykonasz wszystkich domysłów w jak najkrótszym czasie, jaki maszyna wykorzystuje do przedstawienia czasu w identyfikatorze GUID, nigdy nie wygenerujesz tego samego numeru bez względu na liczbę zgadnięć za pomocą wywołania systemowego.

Wydaje mi się, że jeśli znasz faktyczny sposób tworzenia identyfikatora GUID, znacznie skróci to czas odgadywania.

Tony


3
Nie wszystkie identyfikatory GUID są tworzone w ten sposób. Nawet gdyby tak było, Kai musiał tylko czekać, aż znacznik czasu użyty do utworzenia zawijania GUID będzie wystarczająco długi, aby jeden raz użył do utworzenia GUID.
Dour High Arch

3
Przewodniki nie były oparte na adresie Mac od 2000 lub 2001 roku. W jednym z dodatków Service Pack dla NT4 i / lub Win2k całkowicie zmienili algorytm. Są one teraz generowane przez generator liczb losowych, pomniejszony o kilka bitów, które określają, jaki to jest rodzaj przewodnika.
KristoferA

4
nie wszystkie identyfikatory GUID pochodzą z platform Windows ...
AnthonyLambert

OP wspomina o C #, więc jest to Windows. Poza tym, czy GUID V4 to tylko system Windows?
Steven Sudit

5
@Martinho: Ach, ale test jednostkowy Mono dla Guida, w GuidTest.cs, zawiera metodę, która tworzy dwa nowe GUID i sprawdza je pod kątem równości, jeśli nie są równe. Ponieważ Mono buduje się pomyślnie, możemy mieć absolutną pewność, że jego identyfikatory GUID są unikalne! :-)
Steven Sudit,

6

Możesz mieszać identyfikatory GUID. W ten sposób powinieneś uzyskać wynik znacznie szybciej.

Och, oczywiście, jednoczesne uruchamianie wielu wątków jest również dobrym pomysłem, w ten sposób zwiększysz szansę na to, że stan wyścigu wygeneruje ten sam identyfikator GUID dwa razy dla różnych wątków.


6

Identyfikatory GUID mają 124 bity, ponieważ 4 bity zawierają numer wersji.


powód, dla którego nie dodałem tego jako komentarza: nikt o tym nie wspominał i nie wiem, komu powinienem to powiedzieć. :)
Behrooz

Hooooraaaay, zrobiłem to. W jakiejś „prawdziwej” aplikacji, którą napisałem, dostałem kolizję Guida w tabeli z ~ 260 tys. Wierszy. (MSSQL 2008 R2 Express).
Behrooz

6
  1. Idź do laboratorium kriogenicznego w Nowym Jorku.
  2. Zatrzymaj się na (z grubsza) 1990 lat.
  3. Znajdź pracę w Planet Express.
  4. Kup nowy procesor. Zbuduj komputer, uruchom program i umieść go w bezpiecznym miejscu za pomocą pseudo-wiecznej maszyny ruchu, takiej jak maszyna doomsday.
  5. Poczekaj na wynalezienie wehikułu czasu.
  6. Skacz w przyszłość za pomocą wehikułu czasu. Jeśli kupiłeś 128-bitowy procesor 1YHz, przejdź do3,938,453,320 days 20 hours 15 minutes 38 seconds 463 ms 463 μs 374 ns 607 ps po uruchomieniu programu.
  7. ...
  8. ZYSK!!!

... Zajmuje to co najmniej 10,783,127lata, nawet jeśli masz procesor 1YHz, który jest 1,000,000,000,000,000(lub1,125,899,906,842,624 jeśli wolisz używać prefiksu binarnego) razy szybszy niż procesor 1GHz.

Dlatego zamiast czekać na zakończenie obliczeń, lepiej karmić gołębie, które straciły dom z powodu innych n gołębie zabrały je do domu. :(

Lub możesz poczekać, aż wynaleziono 128-bitowy komputer kwantowy. Następnie możesz udowodnić, że GUID nie jest unikalny, używając swojego programu w rozsądnym czasie (być może).


Czekałem na odniesienie do superbohatera w tej odpowiedzi - porażka z plakatu: p - mimo wszystko niesamowite.
IbrarMumtaz

4

Czy próbowałeś begin = begin + new BigInteger((long)1)zamiast ++?


2
nikt nie głosował na odpowiedź, która naprawdę odpowiada na pytanie: P
nawfal

4

Jeśli liczba generowanych UUID jest zgodna z prawem Moore'a, wrażenie, że nigdy nie zabraknie GUID w dającej się przewidzieć przyszłości, jest fałszywe.

W przypadku 2 ^ 128 identyfikatorów UUID zajmie to tylko 18 miesięcy * Log2 (2 ^ 128) ~ = 192 lata, zanim skończą się wszystkie identyfikatory UUID.

I wierzę (bez statystycznego dowodu) w ciągu ostatnich kilku lat od masowego przyjęcia UUID, prędkość, którą generujemy UUID, rośnie znacznie szybciej niż nakazuje prawo Moore'a. Innymi słowy, prawdopodobnie mamy mniej niż 192 lata, zanim będziemy musieli poradzić sobie z kryzysem UUID, czyli o wiele wcześniej niż koniec wszechświata.

Ale ponieważ na pewno nie wypuszczymy ich do końca 2012 roku, pozostawimy to innemu gatunkowi, aby martwił się problemem.


3

Szanse na błąd w kodzie generującym GUID są znacznie wyższe niż szanse algorytmu generującego kolizję. Szanse na błąd w kodzie do testowania identyfikatorów GUID są jeszcze większe. Poddać się.


2

Program, choć zawiera błędy, pokazuje dowód, że identyfikator GUID nie jest unikalny. Ci, którzy próbują udowodnić coś przeciwnego, nie mają racji. To stwierdzenie po prostu dowodzi słabej implementacji niektórych odmian GUID.

Identyfikator GUID nie jest konieczny, z definicji jest unikalny, z definicji jest wysoce unikalny. Właśnie dopracowałeś znaczenie słowa „wysoce”. W zależności od wersji, implementatora (MS lub innych), użycia maszyn wirtualnych itp. Twojej definicji wysoce zmian. (patrz link we wcześniejszym poście)

Możesz skrócić swój 128-bitowy stół, aby udowodnić swoją rację. Najlepszym rozwiązaniem jest użycie formuły skrótu, aby skrócić tabelę z duplikatami, a następnie użyć pełnej wartości po zderzeniu skrótu i ​​na podstawie tego ponownego wygenerowania identyfikatora GUID. Jeśli biegniesz z różnych lokalizacji, przechowujesz pary kluczy mieszających / pełnych w centralnej lokalizacji.

Ps: Jeśli celem jest po prostu wygenerowanie x liczby różnych wartości, utwórz tablicę skrótów o tej szerokości i po prostu sprawdź wartość skrótu.


2

Nie po to, żeby p ** s na ognisku tutaj, ale tak naprawdę się zdarza, i tak, rozumiem żarty żartujesz temu facetowi, ale GUID jest wyjątkowy tylko w zasadzie, wpadłem na ten wątek, ponieważ jest błąd w emulatorze WP7, co oznacza, że ​​za każdym razem, gdy uruchamia się, podaje SAMY GUID przy pierwszym wywołaniu! Jeśli więc teoretycznie nie możesz mieć konfliktu, jeśli istnieje problem z generowaniem wspomnianego GUI, możesz uzyskać duplikaty

http://forums.create.msdn.com/forums/p/92086/597310.aspx#597310


1

Ponieważ część generacji Guida opiera się na czasie obecnej maszyny, moja teoria, aby uzyskać duplikat Guida to:

  1. Wykonaj czystą instalację systemu Windows
  2. Utwórz skrypt startowy, który zresetuje czas do 01.01.2010 12:00:00 w trakcie uruchamiania systemu Windows.
  3. Zaraz po skrypcie startowym uruchamia twoją aplikację do wygenerowania Guid.
  4. Sklonuj tę instalację systemu Windows, aby wykluczyć wszelkie subtelne różnice, które mogą wystąpić podczas kolejnych rozruchów.
  5. Ponownie zrób obraz dysku twardego za pomocą tego obrazu i uruchom komputer kilka razy.

0

Dla mnie .. czas potrzebny na wygenerowanie UUIDv1 przez jeden rdzeń gwarantuje, że będzie on wyjątkowy. Nawet w sytuacji wielordzeniowej, jeśli generator UUID pozwala na wygenerowanie tylko jednego UUID na raz dla określonego zasobu (pamiętaj, że wiele zasobów może całkowicie wykorzystywać te same UUID, choć jest to mało prawdopodobne, ponieważ zasób nieodłącznie stanowi część adresu) będzie mieć więcej niż wystarczającą liczbę identyfikatorów UUID, aby przetrwać do momentu wypalenia znacznika czasu. W tym momencie naprawdę wątpię, żebyś się przejmował.


0

Oto także rozwiązanie:

int main()
{
  QUuid uuid;
  while ( (uuid = QUuid::createUuid()) != QUuid::createUuid() ) { }
  std::cout << "Aha! I've found one! " << qPrintable( uuid.toString() ) << std::endl;
}

Uwaga: wymaga Qt, ale gwarantuję, że jeśli pozwolisz mu działać wystarczająco długo, może go znaleźć.

(Uwaga: tak naprawdę, teraz, gdy na to patrzę, może być coś w algorytmie generowania, który zapobiega zderzeniu dwóch generowanych później Uuidów - ale wątpię w to).


0

Jedynym rozwiązaniem, które udowodni, że identyfikatory GUID nie są unikalne, byłoby posiadanie światowej puli GUID. Za każdym razem, gdy gdzieś generowany jest identyfikator GUID, należy go zarejestrować w organizacji. Albo do diabła, możemy uwzględnić standaryzację, której potrzebują wszystkie generatory GUID, aby zarejestrować je automatycznie i do tego potrzebuje aktywnego połączenia z Internetem!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.