diff --git a/src/main/java/io/trino/tpcds/distribution/DistributionUtils.java b/src/main/java/io/trino/tpcds/distribution/DistributionUtils.java index e49be9b..0cc009d 100644 --- a/src/main/java/io/trino/tpcds/distribution/DistributionUtils.java +++ b/src/main/java/io/trino/tpcds/distribution/DistributionUtils.java @@ -95,13 +95,7 @@ protected static T pickRandomValue(List values, List weights, Ra private static T getValueForWeight(int weight, List values, List weights) { checkArgument(values.size() == weights.size()); - for (int index = 0; index < weights.size(); index++) { - if (weight <= weights.get(index)) { - return values.get(index); - } - } - - throw new TpcdsException("random weight was greater than max weight"); + return values.get(getIndexForWeight(weight, weights)); } protected static T getValueForIndexModSize(long index, List values) @@ -119,13 +113,27 @@ protected static int pickRandomIndex(List weights, RandomNumberStream r private static int getIndexForWeight(int weight, List weights) { - for (int index = 0; index < weights.size(); index++) { - if (weight <= weights.get(index)) { - return index; + // The weights are prefix sums (monotonically non-decreasing), so the smallest index whose + // cumulative weight is >= the target is a lower-bound binary search. This returns the exact + // same index as a linear scan, including when consecutive weights are equal. + int low = 0; + int high = weights.size() - 1; + int result = -1; + while (low <= high) { + int mid = (low + high) >>> 1; + if (weight <= weights.get(mid)) { + result = mid; + high = mid - 1; + } + else { + low = mid + 1; } } - throw new TpcdsException("random weight was greater than max weight"); + if (result == -1) { + throw new TpcdsException("random weight was greater than max weight"); + } + return result; } protected static int getWeightForIndex(int index, List weights)