Когда вы пишете
let id = UUID(), кажется, что это просто генерация случайного набора символов. На деле
Swift запускает целый конвейер: собирает случайные данные из множества аппаратных датчиков: от колебаний напряжения в процессоре до микрозадержек при доступе к памяти, превращает их в непредсказуемые числа через сложные криптоалгоритмы и упаковывает результат в формат по международному стандарту. И все это происходит быстрее, чем вы успеваете моргнуть.
Три стратегии, одна цель:
UUID бывают разными по способу генерации, но все они решают одну задачу: дать идентификатор, который никогда и нигде не повторится без необходимости синхронизироваться с центральным сервером.
- Версия 1 (таймстемп + MAC). Самый старый подход. Берет текущее время с точностью до 100 наносекунд, добавляет MAC-адрес сетевой карты и номер такта на случай отката времени. Гарантия уникальности абсолютная, но есть нюанс: MAC-адрес светит железо, на котором сгенерирован UUID. Для распределенных систем это допустимо, для пользовательских приложений - потенциальная угроза приватности.
- Версия 4 (полностью случайная). Это то, что делает стандартный UUID() в Swift. Никакого времени, никакого железа - только 122 бита криптостойкой случайности. Шесть бит зарезервировано под версию и вариант, остальное - энтропия. Вероятность коллизии настолько мала, что ее можно игнорировать даже при генерации миллиардов идентификаторов в секунду.
- Версия 7 (время + случайность). Новейший стандарт, который пока не встроен в Swift напрямую, но уже активно обсуждается. Берет миллисекундный timestamp и добивает случайными битами. Главное преимущество - монотонность: такие UUID можно сортировать по времени создания, что критично для баз данных и событийных логов.
Откуда берется «достаточно случайно»:
Случайность бывает разная.
arc4random() - быстрая, но предсказуемая, если знать состояние генератора.
UUID требует другого уровня -
CSPRNG (Cryptographically Secure PseudoRandom Number Generator). В Apple-экосистеме за это отвечает
Security.framework, который собирает энтропию буквально из всего:
- Квантовый шум транзисторов CPU (тепловые флуктуации электронов).
- Джиттер тактовых частот между ядрами.
- Вариации времени доступа к RAM и кешу.
- Тайминги нажатий на экран (для iOS) или движений мыши (для macOS).
- Шум сенсоров (акселерометр, гироскоп, тепловые датчики).
- Сетевые пакеты и их интервалы.
Все это смешивается в системном пуле энтропии, через который прогоняется криптопримитив (например, ChaCha20 или Fortuna), и только потом отдается в
UUID().
Почему это не тормозит:
Несмотря на сложность, генерация
UUID в
Swift - одна из самых быстрых операций. На современном железе: 2-5 миллионов идентификаторов в секунду. Секрет в том, что пул энтропии поддерживается постоянно, а
CSPRNG просто выдает из него уже готовые случайные байты. Тяжелая работа (сбор физического шума) происходит в фоне, а ваш
UUID() забирает готовый результат.
Вывод:
UUID в
Swift - это не просто рандомайзер. Это прослойка между вашим кодом и физическими процессами внутри чипа, которые фундаментально непредсказуемы. Каждый вызов
UUID() - маленькое чудо инженерной мысли, где квантовая механика встречается с RFC-стандартами, а результат умещается в 36 символов. Шанс, что два
UUID совпадут, настолько мал, что вы скорее встретите медведя в метро, чем поймаете коллизию.