Prueba simple de que GUID no es único [cerrado]

Resuelto Kai asked hace 15 años • 30 respuestas

Me gustaría demostrar que un GUID no es único en un programa de prueba simple. Esperaba que el siguiente código se ejecutara durante horas, pero no funciona. ¿Cómo puedo hacerlo funcionar?

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

Estoy usando C#.

Kai avatar Nov 10 '09 07:11 Kai
Aceptado

Kai, te he proporcionado un programa que hará lo que quieras usando subprocesos. Tiene licencia bajo los siguientes términos: debes pagarme $0.0001 por hora por cada núcleo de CPU en el que lo ejecutes. Las tarifas se pagan al final de cada mes calendario. Comuníquese conmigo para obtener los detalles de mi cuenta de PayPal lo antes posible.

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

PD: quería probar la biblioteca de extensiones paralelas. Eso fue fácil.

Y usar OutOfMemoryException como flujo de control simplemente parece incorrecto.

EDITAR

Bueno, parece que esto todavía atrae votos. Así que solucioné el problema de GC.KeepAlive(). Y lo cambié para ejecutarlo con C# 4.

Y para aclarar mis términos de soporte: el soporte solo está disponible el 28/feb/2010. Utilice una máquina del tiempo para realizar solicitudes de soporte únicamente ese día.

EDITAR 2 Como siempre, el GC hace un mejor trabajo que yo en la gestión de la memoria; Cualquier intento anterior de hacerlo yo mismo estaba condenado al fracaso.

 avatar Nov 10 '2009 04:11

Esto durará mucho más que horas. Suponiendo que funcione a 1 GHz (lo cual no será así, será mucho más lento que eso), funcionará durante 10790283070806014188970 años. Que es aproximadamente 83 mil millones de veces más larga que la edad del universo.

Suponiendo que se cumpla la ley de Moore , sería mucho más rápido no ejecutar este programa, esperar varios cientos de años y ejecutarlo en una computadora que es miles de millones de veces más rápida. De hecho, cualquier programa que tarde más en ejecutarse que lo que tarda la velocidad de la CPU en duplicarse (aproximadamente 18 meses) se completará antes si espera hasta que las velocidades de la CPU hayan aumentado y compra una nueva CPU antes de ejecutarlo (a menos que lo escriba de manera que se puede suspender y reanudar en hardware nuevo).

rjmunro avatar Nov 10 '2009 01:11 rjmunro

En teoría, un GUID no es único. Aquí está tu prueba:

  • GUID es un número de 128 bits
  • No puede generar 2^128 + 1 o más GUID sin reutilizar los GUID antiguos

Sin embargo, si toda la producción de energía del sol se dirigiera a realizar esta tarea, se enfriaría mucho antes de terminar.

Los GUID se pueden generar utilizando varias tácticas diferentes, algunas de las cuales toman medidas especiales para garantizar que una máquina determinada no genere el mismo GUID dos veces. Encontrar colisiones en un algoritmo particular mostraría que su método particular para generar GUID es malo, pero no probaría nada sobre los GUID en general.

 avatar Nov 10 '2009 01:11