Truco para la creación de tus GUID

Globally Unique Identifier (GUID) es un identificador único que es generado mediante un algoritmo. Originalmente fue implementado por Microsoft llamado como Universally Unique Identifier (UUID), pero más tarde, la Open Software Foundation (OSF) se llamó GUID.

El uso de GUIDs (Identificadores Únicos Globales) en aplicaciones tiene varias ventajas que respaldan su consideración como una buena práctica:

  • Unicidad Global: Los GUIDs son diseñados para ser únicos en todo el mundo. Esto reduce significativamente la probabilidad de colisiones, es decir, la posibilidad de que dos identificadores sean iguales.
  • Generación sin Coordinación: Los GUIDs pueden generarse sin necesidad de coordinación centralizada. Cada instancia puede generar su propio identificador único sin depender de un servidor central.
  • Independencia del Origen: No importa dónde o cuándo se genera un GUID, la probabilidad de que sea único sigue siendo alta. Esto es crucial en entornos distribuidos y sistemas sin conexión constante.
  • Facilita la Integración de Datos: Al utilizar GUIDs como identificadores únicos, se facilita la integración de datos provenientes de diferentes fuentes y sistemas. Cada entidad puede tener un identificador único que se mantiene consistente, simplificando las operaciones de unificación y consulta.
  • Escalabilidad: Cuando se trabaja con bases de datos distribuidas o en sistemas que escalan horizontalmente, los GUIDs son más adecuados para evitar conflictos de identificadores únicos en comparación con identificadores incrementales o secuenciales.
  • Privacidad: A diferencia de los identificadores secuenciales, que pueden revelar información sobre la cantidad de elementos en una base de datos, los GUIDs no proporcionan pistas sobre la cantidad de registros.
  • Fácil Generación: La mayoría de los lenguajes de programación y plataformas ofrecen funciones integradas para generar GUIDs, lo que simplifica su implementación en aplicaciones.
  • Durabilidad: Los GUIDs son adecuados para situaciones donde la durabilidad de los identificadores a lo largo del tiempo es importante, ya que son menos propensos a cambios o reutilización.
  • Integridad Referencial: Al utilizar GUIDs como claves foráneas en relaciones entre tablas de bases de datos, se mejora la integridad referencial, ya que no hay riesgo de colisiones entre claves primarias.

GUID es la mejor manera de identificar inequívocamente un objeto. Este número generado es único, bueno digamos que casi único, tiene un % extremadamente bajo de repetirse. Por el lado de seguridad, es útil debido a que no sabemos cual es el guid siguiente o el anterior. Por ejemplo, supongamos que invocamos a un cliente por el cliente que es un número secuencial. Este se pasa por la url. Si quisiera podría generar un programa que recorra del número 1 hasta 100000 permitiendo recolectar todos los clientes. Esto no podría realizarse si usamos GUID.

En otros caso es crear los guid de lado de los consumidores. Crear un identificador en las bases de datos muchas veces es costoso. Por esta razón, en varias arquitecturas los guid son generados por los servicios. Aquí es donde tenemos nuestra problemática, si nuestros servicios son de alta concurrencia ¿como hacemos para generar una gran cantidad de GUID pro segundo? veamos.

El camino más simple o que todos utilizamos es la siguiente:

List<Guid> List_Simple()
{
    var list = new List<Guid>();
    for (var i = 1; i <= 2000000; i++)
        list.Add(Guid.NewGuid());

    return list;
}

En el ejemplo, podemos ver que tenemos una lista de GUID que será sembrada con dos millones de GUID. Es un bucle sencillo. Este tarda alrededor de 212 milisegundos.

Lo primero que debemos hacer para optimizar es aplicar el tamaño correcto de elementos que tendremos en nuestra lista. Esto reducirá casi un 6% el tiempo de ejecución dando un total de 197 milisegundos.

List<Guid> List_Simple()
{
    var list = new List<Guid>(2000000);
    for (var i = 1; i <= 2000000; i++)
        list.Add(Guid.NewGuid());

    return list;
}

Es posible realizar un método gracias Linq que tal vez sea más claro veamos:

List<Guid> Linq_Simple() 
{
     return Enumerable
         .Range(1, size)
         .Select(n => Guid.NewGuid())
         .ToList();
}

Si bien, la performance será igual que el anterior nos permitirá usar un método en el siguiente ejemplo. Usaremos AsParallel.

List<Guid> Linq_Simple() 
{
     return Enumerable
         .Range(1, size)
         .AsParallel()
         .Select(n => Guid.NewGuid())
         .ToList();
}

Al usar AsParalle() le diremos que esta creación sea multi-hilo. El resultado obtenido en la creación es de 87 milisegundos. Un tiempo de respuesta extremo. Podemos hacerlo más veloz. Si es posible.

Para esto usaremos directamente el método Parallel junto al ForEach que se encuentra mucho más optimizado:

List<Guid> Linq_Simple()
{
    var list = new Guid[size];
    Parallel.ForEach(list, (_, _, index) =>
    {
        list[index] = Guid.NewGuid();
    });

    return list.ToList();
}

Al ejecutar de esta forma obtuvo 42 milisegundos. Desde nuestro ejemplo inicial hasta este último ejemplo hemos reducido un 80% de rendimiento!

Conclusiones

En este artículo, exploramos un ejemplo práctico de cómo podemos iterativamente mejorar la generación masiva de GUIDs en nuestras aplicaciones, aprovechando nuestro conocimiento del lenguaje de programación utilizado. La generación de GUIDs es una tarea común en el desarrollo de aplicaciones, y optimizar este proceso puede tener un impacto significativo en el rendimiento y la eficiencia de nuestras aplicaciones.

El enfoque paso a paso presentado aquí destaca la importancia de realizar mejoras incrementales, evaluando y midiendo el rendimiento en cada etapa del proceso. Hemos utilizado técnicas específicas del lenguaje para optimizar la generación de GUIDs, asegurándonos de mantener la unicidad y la calidad de los identificadores generados.

Para validar la eficacia de nuestras optimizaciones, hemos incorporado pruebas exhaustivas y utilizado la herramienta BenchmarkDotnet para obtener métricas de rendimiento. La realización de pruebas es esencial para garantizar que las mejoras introducidas no comprometan la calidad y unicidad de los GUIDs generados, al tiempo que proporciona una base sólida para tomar decisiones informadas sobre la implementación final.

La utilización de BenchmarkDotnet nos permite medir con precisión el rendimiento de nuestras implementaciones, identificando cualquier impacto positivo o negativo en términos de velocidad y eficiencia. Este enfoque basado en datos nos permite validar nuestras decisiones de diseño y asegurarnos de que nuestras optimizaciones realmente contribuyan a la mejora del rendimiento.

En resumen, este artículo ofrece una guía práctica para abordar la generación masiva de GUIDs de manera eficiente, aprovechando el conocimiento específico del lenguaje de programación. La realización de pruebas y la medición del rendimiento a lo largo del proceso son pasos fundamentales para garantizar que las mejoras implementadas no comprometan la integridad y la unicidad de los identificadores generados.

0 0 votos
Valora la Publicación
Suscribirse
Notificación de
guest
0 Comentarios
Más votados
Nuevos Viejos
Feedback en línea
Ver todos los Comentarios

Comentarios Recientes

0
Nos encantaría conocer tu opinión: ¡comenta!x
Ir a la barra de herramientas