Я читал this question и another question. В одном из этих двух вопросов я также читал, что структура Guid состоит из следующих четырех полей: Int32, Int16, Int16 и Byte [8], поэтому сравнение между двумя Guid должно быть быстрее.Производительность в сравнении GUID
Ну, я использую структуру Guid только для генерации UUID, а затем мне нужно сравнить только те, сгенерированные ранее UUID. Поэтому я хотел бы конвертировать каждый UUID, сгенерированный быстро в формате, сопоставимом.
Я провел несколько тестов, используя следующий код (я получил вдохновение от this question).
struct FastUuid
{
public long _part1;
public long _part2;
public FastUuid(byte[] value)
{
_part1 = BitConverter.ToInt64(value, 0);
_part2 = BitConverter.ToInt64(value, 8);
}
}
static void Main(string[] args)
{
TestUuidCompare(1000000000);
Console.ReadLine();
}
public static void TestUuidCompare(uint numberOfChecks)
{
Guid uuid1 = Guid.NewGuid();
Guid uuid2 = new Guid(uuid1.ToByteArray());
byte[] a1 = uuid1.ToByteArray();
byte[] a2 = uuid2.ToByteArray();
string s1 = uuid1.ToString();
string s2 = uuid2.ToString();
BigInteger b1 = new BigInteger(uuid1.ToByteArray());
BigInteger b2 = new BigInteger(uuid2.ToByteArray());
long l1part1 = BitConverter.ToInt64(uuid1.ToByteArray(), 0); // Parts 1 and 2
long l1part2 = BitConverter.ToInt64(uuid1.ToByteArray(), 8); // of uuid1.
long l2part1 = BitConverter.ToInt64(uuid2.ToByteArray(), 0); // Parts 1 and 2
long l2part2 = BitConverter.ToInt64(uuid2.ToByteArray(), 8); // of uuid2.
long[] la1 = { l1part1, l1part2 }; // Parts 1 and 2 of uuid1.
long[] la2 = { l2part1, l2part2 }; // Parts 1 and 2 of uuid2.
int i1part1 = BitConverter.ToInt32(uuid1.ToByteArray(), 0); // Parts 1, 2, 3
int i1part2 = BitConverter.ToInt32(uuid1.ToByteArray(), 4); // and 4
int i1part3 = BitConverter.ToInt32(uuid1.ToByteArray(), 8); // of
int i1part4 = BitConverter.ToInt32(uuid1.ToByteArray(), 12); // uuid1.
int i2part1 = BitConverter.ToInt32(uuid2.ToByteArray(), 0); // Parts 1, 2, 3
int i2part2 = BitConverter.ToInt32(uuid2.ToByteArray(), 4); // and 4
int i2part3 = BitConverter.ToInt32(uuid2.ToByteArray(), 8); // of
int i2part4 = BitConverter.ToInt32(uuid2.ToByteArray(), 12); // uuid2
FastUuid fast1 = new FastUuid(uuid1.ToByteArray());
FastUuid fast2 = new FastUuid(uuid2.ToByteArray());
// UUID are equal (worse scenario)
Stopwatch sw = new Stopwatch();
bool result;
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = (uuid1 == uuid2);
}
Console.WriteLine("- Guid.Equals: \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = Array.Equals(a1, a2);
}
Console.WriteLine("- Array.Equals(byte): \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = s1.Equals(s2);
}
Console.WriteLine("- String.Equals: \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = b1.Equals(b2);
}
Console.WriteLine("- BigInteger.Equals: \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = (l1part1 == l2part1 && l1part2 == l2part2);
}
Console.WriteLine("- Two long compare: \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = Array.Equals(la1, la2);
}
Console.WriteLine("- Array.Equals(long): \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = (i1part1 == i2part1 && i1part2 == i2part2 && i1part3 == i2part3 && i1part4 == i2part4);
}
Console.WriteLine("- Four int compare: \t{0}", sw.Elapsed);
sw.Reset(); sw.Start();
for (int i = 0; i < numberOfChecks; i++)
{
result = fast1.Equals(fast2);
}
Console.WriteLine("- FastUuid: \t{0}", sw.Elapsed);
}
Со следующими результатами.
- Guid.Equals: 18.911 сек
- Array.Equals (байт): 12.003 сек
- String.equals: 26.159 сек
- BigInteger.Equals: 22,652 с
- Два длинных сравнения: 6,530 s < --- самый быстрый
- Array.Equals (длинный): 11,930 s
- Четыре ИНТ сравнения: 6,795 s
- FastUuid: 1m 26.636 s < --- самый медленный
Почему сравнение FastUuid является самым медленным? Поскольку UUID должен быть ключом к Dictionary
, есть ли способ получить сравнение производительности между двумя длинными и в то же время реализовать UUID с небольшим (16-байтным) объектом/структурой?
EDIT: На самом деле, тесты, которые я выполнял измерения производительности сравнения между двумя UUID, поэтому они имеют мало смысла, чтобы оценить производительность доступа к словарю, потому что, когда я призываю ContainsKey method, он вычисляет хэш-значение UUID. Должен ли я оценивать производительность при вычислении хэш-значения Guid, String, FastUuid и т. Д.? Как работает метод ContainsKey?
Для человека, который downvoted на вопрос OP, то почему? Конструктивная обратная связь всегда приветствуется! – Will
Ваш тест весьма спорный. Вы проверяете крайне маловероятный случай наличия 1000000000 равных указателей. Guid.Equals() оптимизирован для гораздо более вероятного случая, когда они * не будут * равны. –
Я установил 1000000000 проверок, чтобы получить лучшее сравнение. – enzom83