Use BitSet instead of LinkedHashSet to improve the performance of SlotRange construction.

Pull request: #2525
This commit is contained in:
daihuabin
2023-03-09 19:17:24 +08:00
committed by John Blum
parent 2b2e050004
commit 1d293d85a3
3 changed files with 44 additions and 15 deletions

View File

@@ -28,7 +28,7 @@ import org.springframework.util.Assert;
*/
public final class ClusterSlotHashUtil {
private static final int SLOT_COUNT = 16384;
public static final int SLOT_COUNT = 16384;
private static final byte SUBKEY_START = '{';
private static final byte SUBKEY_END = '}';

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.connection;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
@@ -166,11 +168,12 @@ public class RedisClusterNode extends RedisNode {
/**
* @author Christoph Strobl
* @author daihuabin
* @since 1.7
*/
public static class SlotRange {
private final Set<Integer> range;
private final BitSet range;
/**
* @param lowerBound must not be {@literal null}.
@@ -181,19 +184,30 @@ public class RedisClusterNode extends RedisNode {
Assert.notNull(lowerBound, "LowerBound must not be null");
Assert.notNull(upperBound, "UpperBound must not be null");
this.range = new LinkedHashSet<>();
this.range = new BitSet(upperBound + 1);
for (int i = lowerBound; i <= upperBound; i++) {
this.range.add(i);
this.range.set(i);
}
}
public SlotRange(Collection<Integer> range) {
this.range = CollectionUtils.isEmpty(range) ? Collections.emptySet() : new LinkedHashSet<>(range);
if (CollectionUtils.isEmpty(range)) {
this.range = new BitSet(0);
} else {
this.range = new BitSet(ClusterSlotHashUtil.SLOT_COUNT);
for (Integer pos : range) {
this.range.set(pos);
}
}
}
public SlotRange(BitSet range) {
this.range = (BitSet) range.clone();
}
@Override
public String toString() {
return range.toString();
return Arrays.toString(this.getSlotsArray());
}
/**
@@ -201,23 +215,36 @@ public class RedisClusterNode extends RedisNode {
* @return true when slot is part of the range.
*/
public boolean contains(int slot) {
return range.contains(slot);
return range.get(slot);
}
/**
* @return
*/
public Set<Integer> getSlots() {
return Collections.unmodifiableSet(range);
if (range.isEmpty()) {
return Collections.emptySet();
}
LinkedHashSet<Integer> slots = new LinkedHashSet<>(Math.max(2 * range.cardinality(), 11));
for (int i = 0; i < range.length(); i++) {
if (range.get(i)) {
slots.add(i);
}
}
return Collections.unmodifiableSet(slots);
}
public int[] getSlotsArray() {
int[] slots = new int[range.size()];
if (range.isEmpty()) {
return new int[0];
}
int[] slots = new int[range.cardinality()];
int pos = 0;
for (Integer value : range) {
slots[pos++] = value.intValue();
for (int i = 0; i < ClusterSlotHashUtil.SLOT_COUNT; i++) {
if (this.range.get(i)) {
slots[pos++] = i;
}
}
return slots;

View File

@@ -30,6 +30,7 @@ import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Metric;
import org.springframework.data.geo.Metrics;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.ClusterSlotHashUtil;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.RedisClusterNode;
import org.springframework.data.redis.connection.RedisClusterNode.Flag;
@@ -57,6 +58,7 @@ import org.springframework.util.StringUtils;
* @author Thomas Darimont
* @author Mark Paluch
* @author Christoph Strobl
* @author daihuabin
*/
public abstract class Converters {
@@ -606,7 +608,7 @@ public abstract class Converters {
private SlotRange parseSlotRange(String[] args) {
Set<Integer> slots = new LinkedHashSet<>();
BitSet slots = new BitSet(ClusterSlotHashUtil.SLOT_COUNT);
for (int i = SLOTS_INDEX; i < args.length; i++) {
@@ -623,11 +625,11 @@ public abstract class Converters {
int from = Integer.valueOf(slotRange[0]);
int to = Integer.valueOf(slotRange[1]);
for (int slot = from; slot <= to; slot++) {
slots.add(slot);
slots.set(slot);
}
}
} else {
slots.add(Integer.valueOf(raw));
slots.set(Integer.valueOf(raw));
}
}