Skip to content

Commit ae93fc7

Browse files
committed
Support filtering in performance tool
With --filter-value-set and --filter-values flags.
1 parent 98de999 commit ae93fc7

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
@@ -146,7 +146,9 @@ StreamConsumerBuilder lazyInit(boolean lazyInit) {
146146

147147
@Override
148148
public FilterConfiguration filter() {
149-
this.filterConfiguration = new DefaultFilterConfiguration(this);
149+
if (this.filterConfiguration == null) {
150+
this.filterConfiguration = new DefaultFilterConfiguration(this);
151+
}
150152
return this.filterConfiguration;
151153
}
152154

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

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

434+
@CommandLine.Option(
435+
names = {"--filter-value-set", "-fvs"},
436+
description = "filter value set for publishers, range (e.g. 1..15) are accepted",
437+
converter = Utils.FilterValueSetConverter.class)
438+
private List<String> filterValueSet;
439+
440+
@CommandLine.Option(
441+
names = {"--filter-values", "-fv"},
442+
description = "filter values for consumers",
443+
split = ",")
444+
private List<String> filterValues;
445+
434446
static class InstanceSyncOptions {
435447

436448
@CommandLine.Option(
@@ -588,7 +600,6 @@ public Integer call() throws Exception {
588600
maybeDisplayVersion();
589601
maybeDisplayEnvironmentVariablesHelp();
590602
overridePropertiesWithEnvironmentVariables();
591-
592603
Codec codec = createCodec(this.codecClass);
593604

594605
ByteBufAllocator byteBufAllocator = ByteBufAllocator.DEFAULT;
@@ -875,19 +886,43 @@ public Integer call() throws Exception {
875886
producerBuilder.name(producerName).confirmTimeout(Duration.ZERO);
876887
}
877888

878-
java.util.function.Consumer<MessageBuilder> messageBuilderConsumer;
889+
java.util.function.Consumer<MessageBuilder> messageBuilderConsumerTemp;
879890
if (this.superStreams) {
880891
producerBuilder
881892
.superStream(stream)
882893
.routing(msg -> msg.getProperties().getMessageIdAsString());
883894
AtomicLong messageIdSequence = new AtomicLong(0);
884-
messageBuilderConsumer =
895+
messageBuilderConsumerTemp =
885896
mg -> mg.properties().messageId(messageIdSequence.getAndIncrement());
886897
} else {
887-
messageBuilderConsumer = mg -> {};
898+
messageBuilderConsumerTemp = mg -> {};
888899
producerBuilder.stream(stream);
889900
}
890901

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

900-
AtomicLong messageCount = new AtomicLong(0);
901935
ConfirmationHandler confirmationHandler;
902936
if (this.confirmLatency) {
937+
AtomicLong messageCount = new AtomicLong(0);
903938
final PerformanceMetrics metrics = this.performanceMetrics;
904939
final int divisor = Utils.downSamplingDivisor(this.rate);
905940
confirmationHandler =
@@ -935,6 +970,8 @@ public Integer call() throws Exception {
935970

936971
producers.add(producer);
937972

973+
java.util.function.Consumer<MessageBuilder> messageBuilderConsumer =
974+
messageBuilderConsumerTemp;
938975
return (Runnable)
939976
() -> {
940977
final int msgSize = this.messageSize;
@@ -1050,6 +1087,8 @@ public Integer call() throws Exception {
10501087
}
10511088
});
10521089

1090+
consumerBuilder = maybeConfigureForFiltering(consumerBuilder);
1091+
10531092
Consumer consumer = consumerBuilder.build();
10541093
return consumer;
10551094
})
@@ -1126,6 +1165,37 @@ public Integer call() throws Exception {
11261165
return 0;
11271166
}
11281167

1168+
private ConsumerBuilder maybeConfigureForFiltering(ConsumerBuilder consumerBuilder) {
1169+
if (this.filterValues != null && this.filterValues.size() > 0) {
1170+
consumerBuilder =
1171+
consumerBuilder.filter().values(this.filterValues.toArray(new String[0])).builder();
1172+
1173+
if (this.filterValues.size() == 1) {
1174+
String filterValue = filterValues.get(0);
1175+
consumerBuilder =
1176+
consumerBuilder
1177+
.filter()
1178+
.postFilter(msg -> filterValue.equals(msg.getProperties().getTo()))
1179+
.builder();
1180+
} else {
1181+
consumerBuilder =
1182+
consumerBuilder
1183+
.filter()
1184+
.postFilter(
1185+
msg -> {
1186+
for (String filterValue : this.filterValues) {
1187+
if (filterValue.equals(msg.getProperties().getTo())) {
1188+
return true;
1189+
}
1190+
}
1191+
return false;
1192+
})
1193+
.builder();
1194+
}
1195+
}
1196+
return consumerBuilder;
1197+
}
1198+
11291199
private void createStream(Environment environment, String stream) {
11301200
StreamCreator streamCreator =
11311201
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
@@ -859,4 +886,24 @@ static InstanceSynchronization defaultInstanceSynchronization(
859886
throw new RuntimeException(e);
860887
}
861888
}
889+
890+
static int filteringPublishingCycle(int rate) {
891+
if (rate == 0) {
892+
return 100_000;
893+
} else if (rate <= 10) {
894+
return 10;
895+
} else {
896+
return rate / 10;
897+
}
898+
}
899+
900+
static int filteringSubSetSize(int setSize) {
901+
if (setSize <= 3) {
902+
return 1;
903+
} else if (setSize > 10) {
904+
return (int) (setSize * 0.70);
905+
} else {
906+
return setSize - 3;
907+
}
908+
}
862909
}

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
@@ -368,6 +368,27 @@ void commandLineMetricsTest() {
368368
.isEqualTo("-x 1 -y 2");
369369
}
370370

371+
@ParameterizedTest
372+
@CsvSource({"0,100000", "100,10", "1000,100", "50,5", "10,10", "11,1", "5,10"})
373+
void filteringPublishingCycle(int rate, int expected) {
374+
assertThat(Utils.filteringPublishingCycle(rate)).isEqualTo(expected);
375+
}
376+
377+
@ParameterizedTest
378+
@CsvSource({"3,1", "2,1", "4,1", "7,4", "10,7", "15,10"})
379+
void filteringSubSetSize(int setSize, int expected) {
380+
assertThat(Utils.filteringSubSetSize(setSize)).isEqualTo(expected);
381+
}
382+
383+
@Test
384+
void filterValueSetConverter() throws Exception {
385+
CommandLine.ITypeConverter<List<String>> converter = new Utils.FilterValueSetConverter();
386+
assertThat(converter.convert("one")).containsExactly("one");
387+
assertThat(converter.convert("one,two,three")).containsExactly("one", "two", "three");
388+
assertThat(converter.convert("1..10")).hasSize(10).contains("1", "2", "10");
389+
assertThat(converter.convert("5..10")).hasSize(6).contains("5", "6", "10");
390+
}
391+
371392
@Command(name = "test-command")
372393
static class TestCommand {
373394

0 commit comments

Comments
 (0)