add SplitLongs function

This commit is contained in:
Jonathan Shook 2020-10-23 02:35:36 -05:00
parent 0758670f04
commit 7017b6cd53
2 changed files with 81 additions and 0 deletions

View File

@ -0,0 +1,55 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_long;
import io.nosqlbench.virtdata.api.annotations.Categories;
import io.nosqlbench.virtdata.api.annotations.Category;
import io.nosqlbench.virtdata.api.annotations.ThreadSafeMapper;
import java.util.function.LongUnaryOperator;
/**
* Split the value range of Java longs into a number of offsets,
* starting with Long.MIN_VALUE. This method makes it easy to construct
* a set of offsets for testing, or to limit the values used a subset.
* The outputs will range from Long.MIN_VALUE (-2^63) up.
*
* This is not an exactly emulation of token range splits in Apache Cassandra.
*/
@ThreadSafeMapper
@Categories({Category.general})
public class PartitionLongs implements LongUnaryOperator {
// Number of partitions to split the value range into
private final int partitions;
private final long[] starts;
public PartitionLongs(int partitions) {
this.partitions = partitions;
if (partitions < 1) {
throw new RuntimeException("partitions must be at least 1");
} else if (partitions == 1) {
this.starts = new long[]{Long.MIN_VALUE};
} else {
this.starts = new long[partitions];
// because the full interval is signed and Long.MIN_VALUE is 0x8000.0000.0000.0000
long half_interval = Long.MIN_VALUE / partitions;
for (int i = 0; i < starts.length; i++) {
// scaling the interval to whole interval would overflow for 2 partitions
starts[i] = Long.MIN_VALUE + ((i * half_interval) + (i * half_interval));
}
}
}
/**
* This method uses a divisor value with a maximum value of 2^63
*
* @param operand
* @return
*/
@Override
public long applyAsLong(long operand) {
int idx = (int) (operand % starts.length);
return starts[idx];
}
}

View File

@ -0,0 +1,26 @@
package io.nosqlbench.virtdata.library.basics.shared.from_long.to_long;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashSet;
import java.util.Set;
public class PartitionLongsTest {
@Test
void testInvalidInitializerValues() {
Assertions.assertThrows(RuntimeException.class, () -> new PartitionLongs(-3));
Assertions.assertThrows(RuntimeException.class, () -> new PartitionLongs(0));
}
@Test
public void testValueCardinality() {
PartitionLongs f = new PartitionLongs(15);
Set<Long> values = new HashSet<Long>();
for (int i = 0; i < 100; i++) {
values.add(f.applyAsLong(i));
}
Assertions.assertEquals(15, values.size());
}
}