Дубликат, возвращенный Guid.NewGuid ()?

У нас есть приложение, которое генерирует смоделированные данные для одного из наших сервисов в целях тестирования. Каждый элемент данных имеет уникальный Guid. Однако, когда мы запускали тест после некоторых незначительных изменений кода симулятора, все созданные им объекты имели одинаковый Guid.

Был создан единственный объект данных, затем цикл for, в котором были изменены свойства объекта, включая новый уникальный Guid, и он был отправлен в службу через удаленное взаимодействие (сериализуемый, а не маршалинг по ссылке, если это то, что вы думаешь), зацикливайся и делай еще раз и т. д.

Если мы поместим небольшой Thread.Sleep (...) внутрь цикла, он сгенерирует уникальные идентификаторы. Я думаю, что это отвлекающий маневр. Я создал тестовое приложение, которое просто создавало одно руководство за другим и не получало ни одного дубликата.

Моя теория заключается в том, что IL был оптимизирован таким образом, чтобы вызвать такое поведение. Но хватит о моих теориях. Как вы думаете? Я открыт для предложений и способов проверить это.

ОБНОВЛЕНИЕ. Кажется, в моем вопросе много путаницы, поэтому позвольте мне уточнить. Я НЕ думаю, что NewGuid () не работает. Ясно, что это работает. Это отлично! Однако где-то есть ошибка, из-за которой NewGuid () либо: 1) вызываться только один раз в моем цикле 2) вызываться каждый раз в моем цикле, но назначается только один раз 3) еще кое-что, о чем я не думал

Эта ошибка может быть в моем коде (Скорее всего) или где-то в оптимизации.

Итак, повторяя свой вопрос, как мне отладить этот сценарий?

(и спасибо за отличное обсуждение, это действительно помогает мне прояснить проблему в моей голове)

ОБНОВЛЕНИЕ № 2: я бы хотел опубликовать пример, показывающий проблему, но это часть моей проблемы. Я не могу дублировать его за пределами всего набора приложений (клиентских и серверных).

Вот соответствующий фрагмент:

OrderTicket ticket = new OrderTicket(... );

for( int i = 0; i < _numOrders; i++ )
{
    ticket.CacheId = Guid.NewGuid();
    Submit( ticket );  // note that this simply makes a remoting call
}

Если вы думаете, что в IL есть ошибка - используйте Reflector, чтобы отследить ее.

Jim Burger 19.11.2008 05:10

О да. Я думал об этом. Но я изначально предполагал, что это, вероятно, будет в оптимизаторе JIT. Для этого нельзя использовать Reflector.

dviljoen 19.11.2008 06:15

Если вы не думаете, что это ошибка NewGuid, опубликуйте код, который показывает проблему. Или, по крайней мере, опубликуйте код, который было проблема. Также ответьте на вопрос, вызывает ли удаление Thread.Sleep проблему повторного появления проблемы. Я неплохо разбираюсь в экстрасенсорной отладке, но даже лучше с некоторыми деталями.

Mark Brackett 19.11.2008 19:00

да. Сон потока заставил его вести себя правильно, а его удаление вернуло ошибку. Моя проблема усугубляется тем, что я совершенно не могу воспроизвести проблему вне всего этого набора приложений.

dviljoen 19.11.2008 19:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
4
17 028
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Это ошибка в вашем коде. Если вам удалось создать несколько руководств, это наиболее вероятное объяснение. Подсказка здесь в вашем вопросе: «когда мы запускали тест после незначительных изменений кода симулятора, все сгенерированные им объекты имели одинаковый Guid»

Ага, я тоже так думал. Но я не мог его найти. Каждая итерация вызывала NewGuid () каждый раз и каждый раз возвращала один и тот же идентификатор. Предложения?

dviljoen 19.11.2008 04:56

В этом проблема генераторов случайных чисел, никогда нельзя быть уверенным.

tsilb 19.11.2008 04:59

Я на это не куплюсь. В руководстве есть некоторая случайность, и да, теоретически дубликаты «возможны», но не КАЖДЫЙ. Очевидно, проблема не в этом. Что-то не так с нашим кодом или оптимизатором. Моя проблема в том, что я не знаю, как это узнать. Предложения?

dviljoen 19.11.2008 05:03

Как насчет сокращения кода до минимума, который дублирует проблему, и публикации его здесь.

Mitch Wheat 19.11.2008 07:45

См. Этот статья о том, как создается Guid.

Эта статья пришла из ответа Этот.

Итог, если вы создаете GUID слишком быстро, а часы не сдвинулись вперед, поэтому вы получаете такие же. Однако, когда вы засыпаете, он работает, потому что часы переместились.

Спасибо, но опять же, это мне не помогает. Я знаю, что Guid статистически уникален. Моя проблема НЕ в том, что у меня было 2 из 10 000 гидов, которые были обманутыми. Моя проблема заключалась в том, что 10 000 из 10 000 были обманщиками. Это не статистическая коллизия. Это ошибка. Но где? А как найти?

dviljoen 19.11.2008 05:06

Извините, мне пришлось проголосовать за то, что вы не полностью прочитали статью, на которую вы ссылаетесь.

MusiGenesis 19.11.2008 05:40

Код в Submit и OrderTicket тоже будет полезен ...

Вы повторно используете OrderTicket. Я подозреваю, что либо вы (или само удаленное взаимодействие) выполняете пакетные вызовы - вероятно, в отношении количества соединений / ограничений хоста - и выбираете последнее значение CacheId, когда оно, наконец, отправляет их.

Если вы отлаживаете приложение или Thread.Sleep, вы меняете время, чтобы вызов удаленного взаимодействия завершился до того, как вы назначите новый CacheId.

Вы асинхронизируете удаленный вызов? Я бы подумал, что вызов синхронизации будет заблокирован, но я бы проверил с помощью анализатора пакетов, такого как Wireshark, чтобы быть уверенным. В любом случае, просто переход на создание нового OrderTicket на каждой итерации, вероятно, поможет.

Обновлено: вопрос в нет о том, что NewGuid не работает ... поэтому мой предыдущий ответ был удален.

Я знаю, что это ошибка. Но, как и некоторые другие здесь, вы, кажется, зацикливаетесь на уникальности Guid. Проблема не в этом. Опять же, 2 дублирования из 10 000 будут проблемой уникальности. Я получаю 10 000 таких же гидов.

dviljoen 19.11.2008 06:17

Если вы знаете, что это ошибка (то есть вы думаете, что это ошибка приложения), то почему заголовок «Дубликат, возвращенный Guid.NewGuid ()» и теория, что это JIT-оптимизатор вызывает проблему?

Mark Brackett 19.11.2008 06:31

Что касается фиксации на «уникальности Гида», то это даже близко не к тому, что я утверждал. Отсутствие энтропии или неперехваченный сбой malloc (например) может вызвать всевозможные проблемы, включая повторяющиеся Guids (потенциально - опять же, это надуманная теория, поскольку ваш выбор - это нарушенное мышление).

Mark Brackett 19.11.2008 06:33

Пожалуйста, прочтите мое ОБНОВЛЕНИЕ выше. Я не говорю, что NewGuid не работает. Я никогда не собирался даже намекать на это (оглядываясь назад, я просто читаю заголовок своего сообщения, и да, это действительно так звучит ... извините). И у меня нет мышления «избранный сломан». У меня ошибка, которую я не знаю, как ее найти.

dviljoen 19.11.2008 16:58

Тысячи разработчиков используют Guids в .NET. Если бы Guid.NewGuid () вообще имел тенденцию «застревать» на одном значении, проблема возникла бы давно.

Несомненно, виноваты незначительные изменения кода. Тот факт, что Thread.Sleep (который меньше отвлекающий маневр, чем рыба, гниющая на солнце) «решает» вашу проблему, предполагает, что ваши свойства задаются каким-то странным образом, который не может вступить в силу, пока цикл не перестанет блокироваться (либо завершив или с помощью Thread.Sleep). Я даже готов поспорить, что «незначительное изменение» заключалось в сбросе всех свойств из отдельного потока.

Если вы разместили образец кода, это поможет.

Вы проиграете эту ставку. Это единственный поток, который просто генерирует данные объекта по сети.

dviljoen 19.11.2008 06:14

Хороший человек. Я собираюсь случайным образом проголосовать за кучу ваших ответов. :) Извините за замечание "рыба гниет на солнце".

MusiGenesis 21.11.2008 17:24

Я не знаю подробностей того, как генерируются GUID ... пока. Однако в настоящее время моя орг. разводит GUID со скоростью, которая заставит кроликов посрамить. Так что я могу поручиться за то, что GUID не сломаны .. пока.

  • Опубликуйте исходный код, если возможно .. или приложение для воспроизведения клонов. Много раз я обнаружил, что создание этого приложения-клона для воспроизведения проблемы показывает мне проблему.
  • Другой подход - закомментировать «эти незначительные изменения». Если это решит проблему, вы можете сделать треугольник, чтобы найти проблемную строку кода. На глаз мелкие изменения жестко ... Я имею в виду реальный Hard.

Сообщите нам, как это происходит ... звучит интересно.

У меня были бы серьезные проблемы в профессиональном плане, если бы Guid.NewGuid () выдавал ложную информацию каждые несколько миллионов вызовов, не говоря уже о каждом отдельном случае.

MusiGenesis 19.11.2008 09:57
Ответ принят как подходящий

Выполняет ли Submit асинхронный вызов или объект тикета переходит в другой поток на любом этапе.

В примере кода вы повторно используете один и тот же объект. Что делать, если Submit отправляет заявку в фоновом потоке после небольшой задержки (и не принимает копию). Когда вы меняете CacheId, вы фактически обновляете все ожидающие отправки. Это также объясняет, почему Thread.Sleep решает проблему. Попробуй это:

for( int i = 0; i < _numOrders; i++ )
{
    OrderTicket ticket = new OrderTicket(... );
    ticket.CacheId = Guid.NewGuid();
    Submit( ticket );  // note that this simply makes a remoting call
}

Если по какой-то причине это невозможно, попробуйте это и посмотрите, остались ли они такими же:

ticket.CacheId = new Guid("00000000-0000-0000-0000-" + 
     string.Format("{0:000000000000}", i));

@dviljoen: похоже, я все-таки выиграю эту ставку. :)

MusiGenesis 20.11.2008 21:55

Мое чутье подсказывает мне, что что-то в этом роде происходит ...

class OrderTicket 
{
   Guid CacheId {set {_guid = new Guid("00000000-0000-0000-0000-");}
}

Регистрируйте значение CacheId в файле журнала каждый раз, когда он вызывается с трассировкой стека ... Может быть, кто-то еще его устанавливает.

Неа. Он просто обертывает _cacheId, который инициализируется Guid.NewGuid ()

dviljoen 20.11.2008 16:22

Другие вопросы по теме