Skip to content

Commit dedf25c

Browse files
committed
Support filtering in performance tool
With --filter-value-set and --filter-values flags.
1 parent 9f6f314 commit dedf25c

File tree

5 files changed

+167
-6
lines changed

5 files changed

+167
-6
lines changed

src/main/java/com/rabbitmq/stream/impl/StreamConsumerBuilder.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,9 @@ StreamConsumerBuilder lazyInit(boolean lazyInit) {
151151

152152
@Override
153153
public FilterConfiguration filter() {
154-
this.filterConfiguration = new DefaultFilterConfiguration(this);
154+
if (this.filterConfiguration == null) {
155+
this.filterConfiguration = new DefaultFilterConfiguration(this);
156+
}
155157
return this.filterConfiguration;
156158
}
157159

src/main/java/com/rabbitmq/stream/perf/StreamPerfTest.java

+75-5
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,18 @@ public class StreamPerfTest implements Callable<Integer> {
439439
@ArgGroup(exclusive = false, multiplicity = "0..1")
440440
InstanceSyncOptions instanceSyncOptions;
441441

442+
@CommandLine.Option(
443+
names = {"--filter-value-set", "-fvs"},
444+
description = "filter value set for publishers, range (e.g. 1..15) are accepted",
445+
converter = Utils.FilterValueSetConverter.class)
446+
private List<String> filterValueSet;
447+
448+
@CommandLine.Option(
449+
names = {"--filter-values", "-fv"},
450+
description = "filter values for consumers",
451+
split = ",")
452+
private List<String> filterValues;
453+
442454
static class InstanceSyncOptions {
443455

444456
@CommandLine.Option(
@@ -589,7 +601,6 @@ public Integer call() throws Exception {
589601
maybeDisplayVersion();
590602
maybeDisplayEnvironmentVariablesHelp();
591603
overridePropertiesWithEnvironmentVariables();
592-
593604
Codec codec = createCodec(this.codecClass);
594605

595606
ByteBufAllocator byteBufAllocator = ByteBufAllocator.DEFAULT;
@@ -876,19 +887,43 @@ public Integer call() throws Exception {
876887
producerBuilder.name(producerName).confirmTimeout(Duration.ZERO);
877888
}
878889

879-
java.util.function.Consumer<MessageBuilder> messageBuilderConsumer;
890+
java.util.function.Consumer<MessageBuilder> messageBuilderConsumerTemp;
880891
if (this.superStreams) {
881892
producerBuilder
882893
.superStream(stream)
883894
.routing(msg -> msg.getProperties().getMessageIdAsString());
884895
AtomicLong messageIdSequence = new AtomicLong(0);
885-
messageBuilderConsumer =
896+
messageBuilderConsumerTemp =
886897
mg -> mg.properties().messageId(messageIdSequence.getAndIncrement());
887898
} else {
888-
messageBuilderConsumer = mg -> {};
899+
messageBuilderConsumerTemp = mg -> {};
889900
producerBuilder.stream(stream);
890901
}
891902

903+
if (this.filterValueSet != null && this.filterValueSet.size() > 0) {
904+
producerBuilder =
905+
producerBuilder.filterValue(msg -> msg.getProperties().getTo());
906+
List<String> values = new ArrayList<>(this.filterValueSet);
907+
AtomicInteger count = new AtomicInteger();
908+
int subSetSize = Utils.filteringSubSetSize(values.size());
909+
int messageCountCycle = Utils.filteringPublishingCycle(this.rate);
910+
List<String> subSet = new ArrayList<>(subSetSize);
911+
java.util.function.Consumer<MessageBuilder> filteringMessageBuilderConsumer =
912+
b -> {
913+
if (Integer.remainderUnsigned(
914+
count.getAndIncrement(), messageCountCycle)
915+
== 0) {
916+
Collections.shuffle(values);
917+
subSet.clear();
918+
subSet.addAll(values.subList(0, subSetSize));
919+
}
920+
b.properties()
921+
.to(subSet.get(Integer.remainderUnsigned(count.get(), subSetSize)));
922+
};
923+
messageBuilderConsumerTemp =
924+
messageBuilderConsumerTemp.andThen(filteringMessageBuilderConsumer);
925+
}
926+
892927
Producer producer =
893928
producerBuilder
894929
.subEntrySize(this.subEntrySize)
@@ -898,9 +933,9 @@ public Integer call() throws Exception {
898933
.maxUnconfirmedMessages(this.confirms)
899934
.build();
900935

901-
AtomicLong messageCount = new AtomicLong(0);
902936
ConfirmationHandler confirmationHandler;
903937
if (this.confirmLatency) {
938+
AtomicLong messageCount = new AtomicLong(0);
904939
final PerformanceMetrics metrics = this.performanceMetrics;
905940
final int divisor = Utils.downSamplingDivisor(this.rate);
906941
confirmationHandler =
@@ -936,6 +971,8 @@ public Integer call() throws Exception {
936971

937972
producers.add(producer);
938973

974+
java.util.function.Consumer<MessageBuilder> messageBuilderConsumer =
975+
messageBuilderConsumerTemp;
939976
return (Runnable)
940977
() -> {
941978
final int msgSize = this.messageSize;
@@ -1046,6 +1083,8 @@ public Integer call() throws Exception {
10461083
}
10471084
});
10481085

1086+
consumerBuilder = maybeConfigureForFiltering(consumerBuilder);
1087+
10491088
Consumer consumer = consumerBuilder.build();
10501089
return consumer;
10511090
})
@@ -1122,6 +1161,37 @@ public Integer call() throws Exception {
11221161
return 0;
11231162
}
11241163

1164+
private ConsumerBuilder maybeConfigureForFiltering(ConsumerBuilder consumerBuilder) {
1165+
if (this.filterValues != null && this.filterValues.size() > 0) {
1166+
consumerBuilder =
1167+
consumerBuilder.filter().values(this.filterValues.toArray(new String[0])).builder();
1168+
1169+
if (this.filterValues.size() == 1) {
1170+
String filterValue = filterValues.get(0);
1171+
consumerBuilder =
1172+
consumerBuilder
1173+
.filter()
1174+
.postFilter(msg -> filterValue.equals(msg.getProperties().getTo()))
1175+
.builder();
1176+
} else {
1177+
consumerBuilder =
1178+
consumerBuilder
1179+
.filter()
1180+
.postFilter(
1181+
msg -> {
1182+
for (String filterValue : this.filterValues) {
1183+
if (filterValue.equals(msg.getProperties().getTo())) {
1184+
return true;
1185+
}
1186+
}
1187+
return false;
1188+
})
1189+
.builder();
1190+
}
1191+
}
1192+
return consumerBuilder;
1193+
}
1194+
11251195
private void createStream(Environment environment, String stream) {
11261196
StreamCreator streamCreator =
11271197
environment.streamCreator().stream(stream)

src/main/java/com/rabbitmq/stream/perf/Utils.java

+47
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,33 @@ public BiFunction<String, Integer, String> convert(String input) {
473473
}
474474
}
475475

476+
static class FilterValueSetConverter implements ITypeConverter<List<String>> {
477+
478+
@Override
479+
public List<String> convert(String value) {
480+
if (value == null || value.trim().isEmpty()) {
481+
return Collections.emptyList();
482+
}
483+
if (value.contains("..")) {
484+
String[] range = value.split("\\.\\.");
485+
String errorMessage = "'" + value + "' is not valid, valid example values: 1..10, 1..20";
486+
if (range.length != 2) {
487+
throw new CommandLine.TypeConversionException(errorMessage);
488+
}
489+
int start, end;
490+
try {
491+
start = Integer.parseInt(range[0]);
492+
end = Integer.parseInt(range[1]) + 1;
493+
return IntStream.range(start, end).mapToObj(String::valueOf).collect(Collectors.toList());
494+
} catch (NumberFormatException e) {
495+
throw new CommandLine.TypeConversionException(errorMessage);
496+
}
497+
} else {
498+
return Arrays.stream(value.split(",")).collect(Collectors.toList());
499+
}
500+
}
501+
}
502+
476503
static class SniServerNamesConverter implements ITypeConverter<List<SNIServerName>> {
477504

478505
@Override
@@ -918,4 +945,24 @@ static InstanceSynchronization defaultInstanceSynchronization(
918945
throw new RuntimeException(e);
919946
}
920947
}
948+
949+
static int filteringPublishingCycle(int rate) {
950+
if (rate == 0) {
951+
return 100_000;
952+
} else if (rate <= 10) {
953+
return 10;
954+
} else {
955+
return rate / 10;
956+
}
957+
}
958+
959+
static int filteringSubSetSize(int setSize) {
960+
if (setSize <= 3) {
961+
return 1;
962+
} else if (setSize > 10) {
963+
return (int) (setSize * 0.70);
964+
} else {
965+
return setSize - 3;
966+
}
967+
}
921968
}

src/test/java/com/rabbitmq/stream/perf/StreamPerfTestTest.java

+21
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,17 @@ void nativeEpollWorksOnLinux() throws Exception {
511511
assertThat(streamExists(s)).isTrue();
512512
}
513513

514+
@Test
515+
@BrokerVersionAtLeast(BrokerVersion.RABBITMQ_3_13_0)
516+
void shouldNotFailWhenFilteringIsActivated() throws Exception {
517+
Future<?> run = run(builder().filterValueSet("1..15").filterValues("4"));
518+
waitUntilStreamExists(s);
519+
waitOneSecond();
520+
run.cancel(true);
521+
waitRunEnds();
522+
assertThat(consoleOutput()).containsIgnoringCase("summary:");
523+
}
524+
514525
private static <T> Consumer<T> wrap(CallableConsumer<T> action) {
515526
return t -> {
516527
try {
@@ -728,6 +739,16 @@ ArgumentsBuilder nativeEpoll() {
728739
return this;
729740
}
730741

742+
ArgumentsBuilder filterValueSet(String... values) {
743+
arguments.put("filter-value-set", String.join(",", values));
744+
return this;
745+
}
746+
747+
ArgumentsBuilder filterValues(String... values) {
748+
arguments.put("filter-values", String.join(",", values));
749+
return this;
750+
}
751+
731752
String build() {
732753
return this.arguments.entrySet().stream()
733754
.map(e -> "--" + e.getKey() + (e.getValue().isEmpty() ? "" : (" " + e.getValue())))

src/test/java/com/rabbitmq/stream/perf/UtilsTest.java

+21
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,27 @@ void creditsConverterKo(String input) {
385385
.isInstanceOf(TypeConversionException.class);
386386
}
387387

388+
@ParameterizedTest
389+
@CsvSource({"0,100000", "100,10", "1000,100", "50,5", "10,10", "11,1", "5,10"})
390+
void filteringPublishingCycle(int rate, int expected) {
391+
assertThat(Utils.filteringPublishingCycle(rate)).isEqualTo(expected);
392+
}
393+
394+
@ParameterizedTest
395+
@CsvSource({"3,1", "2,1", "4,1", "7,4", "10,7", "15,10"})
396+
void filteringSubSetSize(int setSize, int expected) {
397+
assertThat(Utils.filteringSubSetSize(setSize)).isEqualTo(expected);
398+
}
399+
400+
@Test
401+
void filterValueSetConverter() throws Exception {
402+
CommandLine.ITypeConverter<List<String>> converter = new Utils.FilterValueSetConverter();
403+
assertThat(converter.convert("one")).containsExactly("one");
404+
assertThat(converter.convert("one,two,three")).containsExactly("one", "two", "three");
405+
assertThat(converter.convert("1..10")).hasSize(10).contains("1", "2", "10");
406+
assertThat(converter.convert("5..10")).hasSize(6).contains("5", "6", "10");
407+
}
408+
388409
@Command(name = "test-command")
389410
static class TestCommand {
390411

0 commit comments

Comments
 (0)