From 0fe1beb3d200656e42e45970bfa2b87be8c93ea3 Mon Sep 17 00:00:00 2001 From: brharrington Date: Thu, 1 Aug 2024 14:40:37 -0500 Subject: [PATCH] api: helper for more efficent hash reduction (#1147) --- .../com/netflix/spectator/impl/Hash64.java | 18 ++++++++++++++++++ .../com/netflix/spectator/impl/Hash64Test.java | 15 +++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/spectator-api/src/main/java/com/netflix/spectator/impl/Hash64.java b/spectator-api/src/main/java/com/netflix/spectator/impl/Hash64.java index cf2efd512..7a368bb37 100644 --- a/spectator-api/src/main/java/com/netflix/spectator/impl/Hash64.java +++ b/spectator-api/src/main/java/com/netflix/spectator/impl/Hash64.java @@ -414,4 +414,22 @@ public long computeAndReset() { reset(); return h; } + + /** + * Helper to efficiently reduce hash from to range of {@code [0, n)}. Based on + * fast + * alternative to modulo reduction post. + */ + public static int reduce(long hash, int n) { + return reduce((int) hash, n); + } + + /** + * Helper to efficiently reduce hash from to range of {@code [0, n)}. Based on + * fast + * alternative to modulo reduction post. + */ + public static int reduce(int hash, int n) { + return (int) (((hash & 0xFFFFFFFFL) * (n & 0xFFFFFFFFL)) >>> 32); + } } diff --git a/spectator-api/src/test/java/com/netflix/spectator/impl/Hash64Test.java b/spectator-api/src/test/java/com/netflix/spectator/impl/Hash64Test.java index 6040d6611..4d1473cd8 100644 --- a/spectator-api/src/test/java/com/netflix/spectator/impl/Hash64Test.java +++ b/spectator-api/src/test/java/com/netflix/spectator/impl/Hash64Test.java @@ -272,4 +272,19 @@ public void hashDoubles() { hashes.add(h); } } + + @Test + public void reduce() { + int n = 10; + int[] counts = new int[n]; + Random r = new Random(); + for (int i = 0; i < 100_000; ++i) { + long hash = r.nextLong(); + ++counts[Hash64.reduce(hash, n)]; + } + for (int count : counts) { + int delta = Math.abs(10_000 - count); + Assertions.assertTrue(delta < 1000); + } + } }