TGViewer
yet another dev yet another dev @yet_another_dev · 382 subscribers
Post #114 317
Быстрый расчёт остатка от деления

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

Как известно, индекс бакета в словаре рассчитывается как остаток от деления hashCode на bucketsCount. В C# и многих других языках программирования для этого используется оператор %:

var bucketNum = hashCode % bucketsCount;


В общем случае, эта операция включает в себя деление, которое выполняется медленнее, чем другие арифметические операции. Поэтому была придумана следующая формула:

uint FastModLemier(
uint hashcode,
ulong multiplier,
uint bucketsNum) =>
(uint)((((UInt128)(hashcode
* multiplier))
* bucketsNum) >> 64);


Идея этого подхода в том, что если количество бакетов известно заранее, то можно вычислить значение multiplier по формуле ulong.MaxValue / bucketsNum + 1. Это позволяет заменить деление на умножение и битовые сдвиги. Если интересны подробности и математическое обоснование формулы, то можете ознакомиться со статьёй Дэниела Лемира, разработчика данного метода. Для общего понимания достаточно прочитать главы 1 и 3.2.

В FrozenDictionary и Dictionary используется другой вариант формулы, который, по словам разработчиков Microsoft немного быстрее, что подтверждается результатами бенчмарка (рисунок 1):

uint FastModDotNet(
uint hashcode,
ulong multiplier,
uint bucketsNum) =>
(uint)(((((multiplier
* hashcode) >> 32)
+ 1) * bucketsNum) >> 32);


Кроме того, JIT-компилятор способен оптимизировать код и заменить деление на несколько операций умножения и битовый сдвиг, если значение bucketsCount известно на этапе компиляции. В результате ASM-код для DefaultModConst будет идентичен коду FastModDotNet (рисунок 2).

Код бенчмарка и результаты тут.
  • 👍 12
More from @yet_another_dev
  1. Sep 21, 2026Опубликовал вчера ролик в одной запрещённой в России соцсети про то, как сходил на выборы.…
  2. Sep 20, 2026Мы пришли в 7:50 и очередь уже была 🥲 Пообщались с другими людьми. Многие приехали из дру…
  3. Sep 19, 2026Post #383
  4. Sep 18, 2026Последние пару недель на чат нападают боты со спамом (прикрыл стикером). Поэтому чат тепер…
  5. Sep 17, 2026Что интересного в этой статье: 1. Потрачено $120К, а агенты суммарно отработали около 3-х…
  6. Sep 17, 2026В Microsoft переписали рантайм GitHub Copilot с TypeScript на Rust при помощи агентов. Под…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →