Semplice prova che il GUID non è univoco [chiuso]


323

Vorrei dimostrare che un GUID non è unico in un semplice programma di test. Mi aspettavo che il seguente codice funzionasse per ore, ma non funziona. Come posso farlo funzionare?

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

Sto usando C #.


107
Come sviluppatore di software, cosa diresti se un utente venisse da te e dicesse "non funziona"?
JoshJordan,

152
Aspetta diversi trilioni di anni.
Hobbs

67
Upmodded perché questa è la cosa più divertente che ho visto online oggi.
jrockway,

32
@jrockway - lol. Sto avendo problemi a trovare qualcosa su questa domanda che non sia fondamentalmente sbagliato. Più lo guardo, più diventa divertente.
Tylerl,

243
È unico a livello globale, quindi è unico sul nostro pianeta. Se si desidera un ID veramente unico, è necessario utilizzare un ID universalmente unico (UUID). Presumo che tu sia interessato solo all'unicità nel nostro universo. :-)
tvanfosson,

Risposte:


407

Kai, ho fornito un programma che farà quello che vuoi usando i thread. È concesso in licenza ai seguenti termini: è necessario pagarmi $ 0,0001 l'ora per core della CPU su cui lo si esegue. Le commissioni sono pagabili alla fine di ogni mese di calendario. Vi prego di contattarmi per i dettagli del mio account paypal al più presto.

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: volevo provare la libreria di estensioni parallele. È stato facile.

E usare OutOfMemoryException come flusso di controllo sembra sbagliato.

MODIFICARE

Bene, sembra che questo attiri ancora voti. Quindi ho risolto il problema GC.KeepAlive (). E lo ha cambiato per funzionare con C # 4.

E per chiarire i miei termini di supporto: il supporto è disponibile solo il 28 febbraio 2010. Si prega di utilizzare una macchina del tempo per effettuare richieste di supporto solo in quel giorno.

EDIT 2 Come sempre, il GC fa un lavoro migliore di me nella gestione della memoria; ogni precedente tentativo di farlo da solo era destinato al fallimento.


120
Quell'ultima Console.WriteLine mi ha fatto ridere molto forte. Penso che dovresti lanciare un CommonlyAcceptedCosmologicTheoriesWrongExceptioninvece.
R. Martinho Fernandes,

17
contrassegnare questo come Accettato significa anche che @Kai accetta i termini stipulati da @ligos?
kb.

3
L'impostazione in reserveSomeRam = null;realtà non realizza nulla.
DevinB,

4
@devinb, per favore, spiegalo? sembra che stia liberando i byte precedentemente allocati in modo che il GC possa Collect()farlo. Perché non realizza nulla?
mythz,

3
GuidCollisionDetector. Il nome ha un potenziale
Ufuk Hacıoğulları

226

Questo durerà per molto più di ore. Supponendo che si giri a 1 GHz (che non lo farà - sarà molto più lento di così), funzionerà per 10790283070806014188970 anni. Che è circa 83 miliardi di volte più lungo dell'età dell'universo.

Supponendo che la legge di Moores sia valida, sarebbe molto più veloce non eseguire questo programma, attendere diverse centinaia di anni ed eseguirlo su un computer miliardi di volte più veloce. In effetti, qualsiasi programma che impiega più tempo a funzionare di quanto richieda il raddoppio della velocità della CPU (circa 18 mesi) si completerà prima se aspetti che le velocità della CPU siano aumentate e acquisti una nuova CPU prima di eseguirla (a meno che tu non lo scriva in modo che può essere sospeso e ripreso sul nuovo hardware).


27
accidenti - quindi forse i thread serverali che generano guide sono un'idea migliore?
Kai,

107
4 thread su un processore quad core lo farebbero funzionare in 20 miliardi di volte l'età dell'universo - quindi sì, sarebbe di grande aiuto.
rjmunro,

34
Ho il sospetto che si tratti di un troll, ma per caso non lo è: i fili non sono magici. Se riesci a fare un miliardo di operazioni al secondo su un thread, passare a dieci thread significa che ognuno esegue 1/10 della stessa frequenza. Ogni thread esegue 100 M operazioni al secondo; il numero totale di operazioni al secondo non viene aumentato. Il modo per aumentare il numero di operazioni al secondo è acquistare più computer. Supponiamo di aver acquistato un miliardo di computer in più. Ciò ridurrebbe il problema a prendere solo 10790283070806 anni, che sono ancora più di quattro ore.
Eric Lippert,

10
Penso che rjmunro presuma che ogni thread verrebbe eseguito su un core separato; 83 miliardi di universi / 4 core effettivamente equivalgono approssimativamente a 20 miliardi di universi. È ora di acquistare azioni Intel!
Dour High Arch,

4
@Erik 83 miliardi di processori significa che sarai in grado di farlo in circa il periodo di tempo in cui l'universo è esistito finora. Quindi anche questo non è abbastanza.
rjmunro,

170

Un GUID è teoricamente non unico. Ecco la tua prova:

  • Il GUID è un numero a 128 bit
  • Non è possibile generare 2 ^ 128 + 1 o più GUID senza riutilizzare i vecchi GUID

Tuttavia, se l'intera potenza del sole fosse diretta a svolgere questo compito, si raffredderebbe molto prima che finisse.

I GUID possono essere generati utilizzando una serie di tattiche diverse, alcune delle quali adottano misure speciali per garantire che un determinato computer non generi lo stesso GUID due volte. La ricerca di collisioni in un particolare algoritmo mostrerebbe che il tuo metodo particolare per la generazione di GUID è negativo, ma non proverebbe nulla sui GUID in generale.


44
Pigeonhole Principio per il salvataggio!
yfeldblum,

22
+1 per il sole che va freddo commento. C'è stato un commento interessante da qualche parte sull'inutilità delle chiavi di crittografia> 256 bit. Per iterare su tutti i possibili valori chiave richiederebbe più energia di quanto l'intero universo detenga. Attivare un po 'nella CPU richiede una piccola quantità di energia (è ciò che genera il calore) che, se moltiplicato per 2 ^ 256 volte è un numero davvero enorme che supera l'energia immagazzinata nell'universo, usando E = mc2 l'universo avrebbe bisogno di massa di 2 ^ 227 kg, il nostro sole è 2 ^ 101 kg, quindi 2 ^ 126 soli!
Skizz,

31
@Skizz: questo vale solo per gli attacchi di forza bruta. Quando uno schema di crittografia viene "rotto", significa che può essere risolto in meno tempo della forza bruta, ma il tempo di risoluzione rimane proporzionale alla dimensione della chiave.
Steven Sudit,

1
@StevenSudit: proporzionale all'esponente della dimensione della chiave (a meno che P == NP)
Ihar Bury,

1
@Orlangur Proporzionale alla dimensione della chiave misurata in bit.
Steven Sudit,

137

Naturalmente i GUID possono scontrarsi. Poiché i GUID sono a 128 bit, basta generarli 2^128 + 1e in base al principio del buco del piccione ci deve essere una collisione.

Ma quando diciamo che un GUID è univoco, ciò che realmente intendiamo è che lo spazio delle chiavi è così grande che è praticamente impossibile generare accidentalmente lo stesso GUID due volte (supponendo che stiamo generando i GUID in modo casuale).

Se si genera una sequenza di nGUID in modo casuale, la probabilità di almeno una collisione è approssimativamente p(n) = 1 - exp(-n^2 / 2 * 2^128)(questo è il problema del compleanno con il numero di possibili compleanni 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

Per rendere questi numeri concreti, 2^60 = 1.15e+18. Quindi, se generi un miliardo di GUID al secondo, ci vorranno 36 anni per generare 2^60GUID casuali e anche allora la probabilità che tu abbia una collisione è ancora 1.95e-03. È più probabile che tu venga ucciso ad un certo punto della tua vita ( 4.76e-03) rispetto a trovare una collisione nei prossimi 36 anni. In bocca al lupo.


239
Se vieni ucciso ad un certo punto della tua vita, è probabile che alla fine sarà.
Michael Myers

25
@mmyers: punto eccellente. Ciò significa che le mie possibilità di essere ucciso in questo momento sono assurdamente basse, dal momento che questa non è la fine della mia vita. Oh, aspetta ...
Steven Sudit,

Inoltre, se due GUID vengono creati in un breve periodo, le possibilità che vengano utilizzate all'interno dello stesso sistema sono scarse. Pertanto, ciò aumenta l'unicità.
AMissico,

Questi numeri e riferimenti al problema del compleanno non hanno senso. Gli algoritmi di generazione GUID non generano valori sull'intero intervallo con uguale probabilità. In effetti IIRC l'algoritmo originale utilizzava l'indirizzo MAC del PC di generazione + l'ora corrente come parte del risultato - il che riduce il rischio di collisione con le Guide generate su altri PC, ma ovviamente riduce lo spazio chiave.
Joe,

17
Stai assumendo che la probabilità di essere assassinato sia una costante per tutti gli esseri umani. Ma chiaramente le persone che scrivono commenti malvagi nei post del forum sono il tipo di persone che hanno maggiori probabilità di essere uccise rispetto alla persona media.
Jay,

61

Se sei preoccupato per l'unicità, puoi sempre acquistare nuovi GUID in modo da poter eliminare quelli vecchi. Ne metterò un po 'su eBay, se lo desideri.


13
Fantastico: quanto per il set completo, da 0 a (2 ^ 128) -1?
Steve314,

23
In vendita, $ 0,01 per 1k GUID. Aggiungerò alcuni campanelli eolici di bambù se ordini nei prossimi 60 minuti.
ctacke,

7
Il mio set è più esclusivo e di qualità superiore. Vengono ricontrollati e verificati, il che li rende validi $ 1 per GUID. Puoi persino acquistarli in lotti se non vuoi fare l'intero investimento in una volta sola. Dovrò comunque pagare un sovrapprezzo di $ 10 per lotto.
Thomas,

3
Ti preparerò su un piano mensile e ti darò guide illimitate al giusto prezzo. ^ Quei ragazzi stanno cercando di truffarti e venderti guide troppo care. Ti venderò guide di qualità prodotte in Cina!
ErocM,

47

Personalmente, penso che il "Big Bang" sia stato causato quando due GUID si sono scontrati.


4
Ricorda solo che ci vuole un tipo di programmatore "speciale" per farlo ...
AnthonyLambert,

Mi piacerebbe sentire il tuo ragionamento sulla tua teoria. Penso che potremmo iniziare una nuova religione basata su questo e reclutare T.Cruise!
ErocM,

@ErocM; Vedi "Brane cosmology" ( en.wikipedia.org/wiki/Brane_cosmology ) e "Membrane (M-Theory)" ( en.wikipedia.org/wiki/Membrane_(M- Theory ) ). L'idea è che se due brane toccano un nuovo universo viene creato. Pertanto, si può dedurre che se due GUID toccano, viene così creato un nuovo universo.
AMissico,

2
Se Timecop ci ha insegnato qualcosa è che la stessa materia non può occupare lo stesso spazio in un dato momento. Quindi, se due GUID dovessero scontrarsi, si consumerebbero l'un l'altro e l'implosione che ne deriverebbe genererebbe un buco nero, divorando l'intero universo. Quindi, in realtà, non creerebbe un universo, lo distruggerà.
AJC

42

Puoi mostrarlo in O (1) tempo con una variante dell'algoritmo quantistico di bogosort .

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

21
Ricevo un'eccezione quando chiamo Destroy (). Sulla base del testo, penso che il mio computer manchi dell'hardware necessario per distruggere l'universo attuale. Sai dove potrei essere in grado di ottenerlo?
Steven Sudit,

11
@Steven: Nah, alcuni gestori si sono preoccupati troppo di come quell'API sarebbe sembrata al pubblico e hanno imposto che fallisse sempre per "motivi di sicurezza". Se si guarda alla sorgente del metodo c'è solo che una linea: throw new MundaneHardwareException();. Comunque, ho sentito che i ragazzi del CERN hanno una specie di Big Hadron Thingy che potrebbe fare il trucco ...
R. Martinho Fernandes,

7
@Martinho: Ah, ok. Esaminerò la sostituzione Universe.Current.Destroy()con Cern.Lhc.DestroyThisUniverse().
Steven Sudit,

61
Sapevo che c'era un motivo per cui ho programmato a Haskell. Questi effetti collaterali stanno diventando spaventosi.
Edward KMETT,

6
"Esiste una teoria secondo cui se mai qualcuno scopre esattamente a cosa serve l'Universo e perché è qui, scomparirà istantaneamente e sarà sostituito da qualcosa di ancora più bizzarro inspiegabile. C'è un'altra teoria che afferma che questo è già successo ". - Douglas Adams, The Hitchhiker's Guide to the Galaxy
Mike Pirnat,

28

Eventuali due GUID sono probabilmente unici (non uguali).

Vedi questa voce SO e da Wikipedia

Sebbene non sia garantito che ogni GUID generato sia univoco, il numero totale di chiavi univoche (2 ^ 128 o 3.4 × 10 ^ 38) è così grande che la probabilità che lo stesso numero venga generato due volte è molto piccola. Ad esempio, considera l'universo osservabile, che contiene circa 5 × 10 ^ 22 stelle; ogni stella potrebbe quindi avere 6,8 × 10 ^ 15 GUID universalmente unici.

Quindi probabilmente devi aspettare ancora molti miliardi di anni e sperare di averne colpito uno prima dell'universo, dato che sappiamo che finisce.


quindi 2 ^ 128 non è il numero corretto di possibili guide?
Kai,

21
È. Perché pensi che 2 ^ 128 sia un numero piccolo?
jrockway,

Sì, 2 ^ 128 è il numero corretto di possibili guide.
Graviton,

3
È un numero infernale. $ irb >> 2**128 => 340282366920938463463374607431768211456
adamJev

45
@Infinity - Anche a te?
Austin Richardson,

27

[Aggiornamento:] Come sottolineato nei commenti seguenti, i più recenti GUID MS sono V4 e non usano l'indirizzo MAC come parte della generazione GUID (non ho visto alcuna indicazione di un'implementazione V5 da parte di MS, quindi se qualcuno ha un link di conferma che fammi sapere). Con V4, però, il tempo è ancora un fattore, e le probabilità contro la duplicazione dei GUID rimangono così piccole da essere irrilevanti per qualsiasi uso pratico. Certamente non sarebbe probabilmente mai possibile generare un GUID duplicato da un solo test di sistema come quello che l'OP stava cercando di fare.

Alla maggior parte di queste risposte manca un punto vitale sull'implementazione GUID di Microsoft. La prima parte del GUID si basa su un timestamp e un'altra parte si basa sull'indirizzo MAC della scheda di rete (o su un numero casuale se non è installata alcuna scheda NIC).

Se lo capisco correttamente, significa che l'unico modo affidabile per duplicare un GUID sarebbe quello di eseguire simultaneamente generazioni GUID su più macchine in cui gli indirizzi MAC erano gli stessi E dove gli orologi su entrambi i sistemi erano nello stesso momento esatto in cui la generazione si è verificato (il timestamp si basa su millisecondi se lo capisco correttamente) .... anche allora ci sono molti altri bit nel numero che sono casuali, quindi le probabilità sono ancora minuscole.

Per tutti gli scopi pratici i GUID sono universalmente unici.

C'è una descrizione abbastanza buona del MS GUID sul blog "The Old New Thing"


3
Questo è effettivamente possibile quando si utilizza la virtualizzazione. Puoi e ottieni guide duplicate.
Goran,

8
Raymond è obsoleto nella parte dell'indirizzo MAC, tuttavia Microsoft non li utilizza più. Vedi en.wikipedia.org/wiki/GUID#Algorithm per la differenza tra le guide V1 e V4.
Michael Stum

1
Questo non è più il caso. L'attuale schema V5 è solo 128 bit di pura bontà pseudocasuale.
Edward KMETT,

divertente come dichiari tutto quello che ho fatto un mese dopo di me e ottieni 16 punti e ho ancora 0?
AnthonyLambert,

1
Ya Tony, c'è qualcosa di strano in questo. Quando ho risposto al post, c'erano solo 3 o 4 risposte e non mi ricordavo di aver visto le tue ... se avessi avuto, l'avrei solo votato. In genere non rispondo alle domande quando ci sono già altre risposte che lo coprono abbastanza bene (motivo per cui probabilmente ho un rappresentante generale piuttosto basso).
Stephen M. Redd,

23

Ecco un piccolo metodo di estensione che puoi usare se vuoi controllare l'unicità di guid in molti punti del tuo codice.

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

Per chiamarlo, è sufficiente chiamare Guid.IsUnique ogni volta che si genera un nuovo guid ...

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

... diamine, ti consiglio persino di chiamarlo due volte per assicurarmi che sia andato bene nel primo round.


2
In che modo ciò garantisce che this guidnon sia mai stato generato altrove in questo mondo? : p Diamine, abbiamo bisogno di un pool di guide mondiali. :)
nawfal,

19

Contando fino a 2 ^ 128 - ambizioso.

Immaginiamo di poter contare 2 ^ 32 ID al secondo per macchina - non così ambizioso, dal momento che non è nemmeno 4,3 miliardi al secondo. Dedichiamo 2 ^ 32 macchine a tale compito. Inoltre, consente di ottenere 2 ^ 32 civiltà per dedicare ciascuna le stesse risorse all'attività.

Finora, possiamo contare 2 ^ 96 ID al secondo, il che significa che conteremo per 2 ^ 32 secondi (poco più di 136 anni).

Ora, tutto ciò di cui abbiamo bisogno è di ottenere 4.294.967.296 civiltà a ciascuna dedicata 4.294.967.296 macchine, ogni macchina in grado di contare 4.294.967.296 ID al secondo, puramente per questo compito per i prossimi 136 anni circa - suggerisco di iniziare subito questo compito essenziale; -)


17

Bene, se il tempo di esecuzione di 83 miliardi di anni non ti spaventa, pensa che dovrai anche archiviare i GUID generati da qualche parte per verificare se ne hai un duplicato; la memorizzazione di 2 ^ 128 numeri a 16 byte richiederebbe solo di allocare 4951760157141521099596496896 terabyte di RAM in anticipo, quindi immaginando di avere un computer che potrebbe adattarsi a tutto ciò e che in qualche modo trovi un posto per acquistare DIMM terabyte a 10 grammi ciascuno, combinati pesa più di 8 masse terrestri, quindi puoi spostarla seriamente dall'orbita attuale, prima ancora di premere "Esegui". Pensa due volte!


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

Non stai incrementando, beginquindi la condizione begin < endè sempre vera.


1
no - perché non posso ripetere bigint
Kai

3
Importa davvero se scorre per sempre contro il looping 340282366920938463463374607431768211456?
Jay,

3
quindi ... preferiresti essere preso a pugni 340282366920938463463374607431768211456 volte o per sempre!?!?!?
ErocM,

in realtà questo è ciò che risponde veramente alla domanda! e nessun voto: p
nawfal


9

Presumibilmente hai motivo di credere che l'algoritmo per la produzione di Guide non stia producendo numeri veramente casuali, ma in realtà sta pedalando con un periodo << 2 ^ 128.

ad esempio il metodo RFC4122 utilizzato per derivare GUID che fissa i valori di alcuni bit.

La prova del ciclismo dipenderà dalla possibile dimensione del periodo.

Per piccoli periodi, la tabella hash di hash (GUID) -> GUID con sostituzione in caso di collisione se i GUID non corrispondono (terminano in caso affermativo) potrebbe essere un approccio. Considera anche di fare la sostituzione solo una frazione casuale del tempo.

In definitiva, se il periodo massimo tra le collisioni è abbastanza grande (e non è noto in anticipo), qualsiasi metodo produrrà solo una probabilità che la collisione sarebbe trovata se esistesse.

Tieni presente che se il metodo di generazione delle guide è basato sull'orologio (vedi RFC), potrebbe non essere possibile determinare se esistono collisioni perché (a) non sarai in grado di attendere abbastanza a lungo affinché l'orologio si avvolga, oppure (b) non è possibile richiedere un numero sufficiente di Guide entro un orologio per forzare una collisione.

In alternativa, potresti essere in grado di mostrare una relazione statistica tra i bit nella Guida o una correlazione di bit tra le Guide. Tale relazione potrebbe rendere altamente probabile che l'algoritmo sia difettoso senza essere necessariamente in grado di trovare una collisione effettiva.

Ovviamente, se vuoi solo dimostrare che le Guide possono scontrarsi, allora una prova matematica, non un programma, è la risposta.


8

Non capisco perché nessuno abbia menzionato l'aggiornamento della tua scheda grafica ... Sicuramente se avessi una NVIDIA Quadro FX 4800 di fascia alta o qualcosa del genere (192 core CUDA) questo andrebbe più veloce ...

Ovviamente se potessi permetterti un paio di NVIDIA Qadro Plex 2200 S4 (a 960 core CUDA ciascuno), questo calcolo urlerebbe davvero . Forse NVIDIA sarebbe disposta a prestarti alcuni per una "dimostrazione di tecnologia" come acrobazia pubblicitaria?

Sicuramente vorrebbero far parte di questo calcolo storico ...


hmmmm ..... Potrei eseguirlo sulla nostra griglia di 10.000 nodi al lavoro.
AnthonyLambert,

8

Ma devi essere sicuro di avere un duplicato o ti importa solo se può esserci un duplicato. Per essere sicuro di avere due persone con lo stesso compleanno, hai bisogno di 366 persone (senza contare l'anno bisestile). Perché ci sia una probabilità superiore al 50% di avere due persone con lo stesso compleanno, hai bisogno solo di 23 persone. Questo è il problema del compleanno .

Se si dispone di 32 bit, sono necessari solo 77.163 valori per avere una probabilità superiore al 50% di un duplicato. Provalo:

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

Adesso 128 bit sono molti, quindi stai ancora parlando di un gran numero di elementi, dandoti comunque una bassa possibilità di collisione. Avresti bisogno del seguente numero di record per le probabilità date usando un'approssimazione:

  • 0,8 miliardi di miliardi per una probabilità 1/1000 di una collisione
  • 21,7 miliardi di miliardi con il 50% di probabilità che si verifichi una collisione
  • 39,6 miliardi di miliardi con una probabilità del 90% di una collisione

Ci sono circa 1E14 e-mail inviate all'anno, quindi sarebbero circa 400.000 anni a questo livello prima che tu abbia il 90% di possibilità di averne due con lo stesso GUID, ma è molto diverso dal dire che devi eseguire un computer 83 miliardi volte l'età dell'universo o che il sole diventasse freddo prima di trovare un duplicato.


7

Non vi mancate tutti un punto importante?

Ho pensato che i GUID fossero generati usando due cose che rendono le probabilità che fossero globalmente uniche piuttosto alte. Uno è che vengono seminati con l'indirizzo MAC della macchina su cui ci si trova e due usano il tempo in cui sono stati generati più un numero casuale.

Quindi, a meno che non lo si esegua sulla macchina reale e si esegua tutto ciò che si suppone nel minor tempo che la macchina utilizza per rappresentare un tempo nel GUID, non si genererà mai lo stesso numero, indipendentemente dal numero di ipotesi effettuate utilizzando la chiamata di sistema.

Immagino che se si conosce il modo in cui viene realizzato un GUID si accorcerebbe effettivamente il tempo di indovinare sostanzialmente.

Tony


3
Non tutti i GUID vengono creati in questo modo. Anche se lo fossero, Kai deve solo aspettare fino a quando il timestamp utilizzato per creare il GUID si avvolge abbastanza volte per essere usato di nuovo per uno che ha usato per creare un GUID.
Dour High Arch,

3
Le guide non si basano sull'indirizzo mac dal 2000 o 2001. A partire da uno dei service pack per NT4 e / o Win2k hanno cambiato completamente l'algoritmo. Ora sono generati da un generatore di numeri casuali, meno alcuni bit che identificano il tipo di guida.
Kristofer,

4
non tutti i GUID provengono da piattaforme Windows ...
AnthonyLambert,

OP menziona C #, quindi è Windows. Inoltre, V4 GUID è una cosa solo per Windows?
Steven Sudit,

5
@Martinho: Ah, ma il test unitario di Mono per Guid, in GuidTest.cs, contiene un metodo che crea due nuovi GUID e li controlla per l'uguaglianza, fallendo se sono uguali. Poiché Mono viene compilato correttamente, possiamo essere assolutamente certi che i suoi GUID siano unici! :-)
Steven Sudit,

6

È possibile eseguire l'hashing dei GUID. In questo modo, dovresti ottenere un risultato molto più velocemente.

Oh, ovviamente, anche eseguire più thread contemporaneamente è una buona idea, in questo modo aumenterai la possibilità che una condizione di competizione generi lo stesso GUID due volte su thread diversi.


6

I GUID sono 124 bit perché 4 bit contengono il numero di versione.


il motivo per non aggiungere questo come commento: nessuno lo ha menzionato e non so a chi dovrei dirlo. :)
Behrooz,

Hooooraaaay l'ho fatto. In alcune app "vere" che ho scritto, ho avuto una collisione di Guid in un tavolo con ~ 260k Righe. (MSSQL 2008 R2 Express).
Behrooz,

6
  1. Vai al laboratorio di criogenia a New York City.
  2. Congelati per (circa) 1990 anni.
  3. Trova un lavoro presso Planet Express.
  4. Acquista una CPU nuova di zecca. Costruisci un computer, esegui il programma e posizionalo in un luogo sicuro con una macchina da movimento pseudo-perpetua come la macchina del giorno del giudizio.
  5. Attendere fino all'invenzione della macchina del tempo.
  6. Salta al futuro usando la macchina del tempo. Se hai acquistato una CPU a 1 bit da 128 bit, vai a 3,938,453,320 days 20 hours 15 minutes 38 seconds 463 ms 463 μs 374 ns 607 psdopo quando hai iniziato a eseguire il programma.
  7. ...?
  8. PROFITTO!!!

... Ci vogliono almeno 10,783,127anni anche se hai una CPU da 1YHz che è 1,000,000,000,000,000(o 1,125,899,906,842,624se preferisci usare il prefisso binario) volte più veloce della CPU da 1GHz.

Quindi, piuttosto che attendere il completamento del calcolo, sarebbe meglio nutrire i piccioni che hanno perso la casa perché altri npiccioni hanno preso la loro casa. :(

In alternativa, è possibile attendere fino all'invenzione del computer quantistico a 128 bit. Quindi potresti provare che il GUID non è unico, usando il tuo programma in tempi ragionevoli (forse).


Stavo aspettando un riferimento a un supereroe in questa risposta - fallisci per poster: p - fantastico comunque.
IbrarMumtaz,

4

Hai provato begin = begin + new BigInteger((long)1)al posto di begin ++?


2
nessuno ha votato per la risposta che risponde veramente alla domanda: P
nawfal

4

Se il numero di UUID che viene generato segue la legge di Moore, l'impressione di non rimanere mai senza GUID nel prossimo futuro è falsa.

Con 2 ^ 128 UUID, ci vorranno solo 18 mesi * Log2 (2 ^ 128) ~ = 192 anni, prima che finiamo tutti gli UUID.

E credo (senza prove statistiche di sorta) negli ultimi anni dall'adozione in massa dell'UUID, la velocità che stiamo generando UUID sta aumentando molto più velocemente di quanto impone la legge di Moore. In altre parole, probabilmente abbiamo meno di 192 anni prima di dover affrontare la crisi UUID, che è molto prima della fine dell'universo.

Ma dal momento che sicuramente non li esauriremo entro la fine del 2012, lasceremo ad altre specie di preoccuparsi del problema.


3

Le probabilità di un bug nel codice di generazione del GUID sono molto più alte delle probabilità dell'algoritmo che genera una collisione. Le probabilità di un bug nel tuo codice per testare i GUID sono ancora maggiori. Abbandonare.


2

Il programma, sebbene i suoi errori, mostra la prova che un GUID non è univoco. Coloro che cercano di dimostrare il contrario non hanno ragione. Questa affermazione dimostra solo la debole implementazione di alcune delle varianti GUID.

Un GUID non è necessario univoco per definizione, è altamente unico per definizione. Hai appena raffinato il significato di altamente. A seconda della versione, dell'attuatore (MS o di altri), dell'uso di VM, ecc., La tua definizione di cambiamenti significativi. (vedi link nel post precedente)

Puoi abbreviare la tabella a 128 bit per dimostrare il tuo punto. La soluzione migliore è utilizzare una formula di hash per abbreviare la tabella con i duplicati, quindi utilizzare il valore completo una volta che l'hash si scontra e sulla base di quella rigenerazione di un GUID. Se corri da posizioni diverse, dovresti archiviare le tue coppie di chiavi hash / complete in una posizione centrale.

Ps: se l'obiettivo è solo generare un numero x di valori diversi, crea una tabella hash di questa larghezza e controlla semplicemente il valore hash.


2

Non per p ** s sul falò qui, ma in realtà succede, e sì, capisco lo scherzo che hai dato a questo ragazzo, ma il GUID è unico solo in linea di principio, mi sono imbattuto in questo thread perché c'è un bug nell'emulatore WP7 che significa che ogni volta che si avvia emette il SAME GUID la prima volta che viene chiamato! Quindi, laddove in teoria non si può avere un conflitto, se si verifica un problema durante la generazione di detta GUI, è possibile ottenere duplicati

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


1

Poiché parte della generazione di Guid si basa sul tempo della macchina corrente, la mia teoria per ottenere una guida duplicata è:

  1. Eseguire un'installazione pulita di Windows
  2. Crea uno script di avvio che reimposta l'ora al 01-01-2010 alle 12:00:00 proprio all'avvio di Windows.
  3. Subito dopo lo script di avvio, avvia l'applicazione per generare un Guid.
  4. Clonare questa installazione di Windows, in modo da escludere eventuali sottili differenze che potrebbero verificarsi nei successivi avviamenti.
  5. Ri-immagine del disco rigido con questa immagine e avviare il computer alcune volte.

0

Per me .. il tempo impiegato da un singolo core per generare un UUIDv1 garantisce che sarà unico. Anche in una situazione multi-core se il generatore UUID consente di generare un solo UUID alla volta per la tua risorsa specifica (tieni presente che più risorse possono utilizzare totalmente gli stessi UUID, anche se è improbabile poiché la risorsa è intrinsecamente parte dell'indirizzo) avrà UUID più che sufficienti per durare fino allo scadere del timestamp. A quel punto dubito davvero che ti importerebbe.


0

Ecco anche una soluzione:

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

Nota: richiede Qt, ma garantisco che se lo lasci funzionare abbastanza a lungo, potrebbe trovarne uno.

(Nota nota: in realtà, ora che lo sto guardando, potrebbe esserci qualcosa nell'algoritmo di generazione che impedisce a due uuidi successivamente generati di scontrarsi, ma ne dubito).


0

L'unica soluzione per dimostrare che i GUID non sono unici sarebbe avere un pool di GUID mondiali. Ogni volta che un GUID viene generato da qualche parte, dovrebbe essere registrato nell'organizzazione. O diamine, potremmo includere una standardizzazione che tutti i generatori GUID devono registrare automaticamente e per questo ha bisogno di una connessione Internet attiva!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.