Skip to content

Commit 026cb24

Browse files
committed
DPL: benchmark a relay/consume cycle across many inputs
Every existing benchmark here uses one or two inputs, which is exactly the regime where per-input storage costs nothing to speak of, so none of them can see a change to how a slot holds its messages. Sweep 1/8/32/128 instead. Note this is the only benchmark using consumeWhenAll, which looks the TimesliceIndex up in the service registry (CompletionPolicyHelpers). The others use consumeWhenAny and never do, which is why BenchmarkServices does not register it and why it has to be registered here -- without it the benchmark throws at every input count, including one.
1 parent 03e80c5 commit 026cb24

1 file changed

Lines changed: 79 additions & 0 deletions

File tree

Framework/Core/test/benchmark_DataRelayer.cxx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <Monitoring/Monitoring.h>
2626
#include <fairmq/TransportFactory.h>
2727
#include <cstring>
28+
#include <cstdio>
2829
#include <iterator>
2930
#include <vector>
3031
#include <uv.h>
@@ -402,4 +403,82 @@ static void BM_RelayMultiplePayloads(benchmark::State& state)
402403

403404
BENCHMARK(BM_RelayMultiplePayloads)->Arg(10)->Arg(100)->Arg(1000);
404405

406+
// Every benchmark above uses one or two inputs, which is exactly the regime
407+
// where per-input storage costs nothing to speak of. Sweep the number of inputs
408+
// so a change to how a slot holds its messages is visible where it matters.
409+
//
410+
// Note this is the only benchmark here using consumeWhenAll, which needs the
411+
// TimesliceIndex from the registry (CompletionPolicyHelpers.cxx). The others use
412+
// consumeWhenAny and never look it up, which is why BenchmarkServices does not
413+
// register it and why it has to be registered here.
414+
static void BM_RelayManyInputs(benchmark::State& state)
415+
{
416+
BenchmarkServices services;
417+
size_t const nInputs = state.range(0);
418+
419+
std::vector<InputSpec> specs;
420+
std::vector<InputRoute> inputs;
421+
std::vector<DataHeader> prototypes;
422+
specs.reserve(nInputs);
423+
for (size_t i = 0; i < nInputs; ++i) {
424+
char description[16];
425+
snprintf(description, sizeof(description), "DATA%03zu", i);
426+
o2::header::DataDescription desc;
427+
desc.runtimeInit(description);
428+
specs.emplace_back(InputSpec{"in", "TST", desc});
429+
DataHeader dh;
430+
dh.dataOrigin = "TST";
431+
dh.dataDescription = desc;
432+
dh.subSpecification = 0;
433+
dh.splitPayloadIndex = 0;
434+
dh.splitPayloadParts = 1;
435+
dh.payloadSize = 100;
436+
prototypes.push_back(dh);
437+
}
438+
for (size_t i = 0; i < nInputs; ++i) {
439+
inputs.emplace_back(InputRoute{specs[i], i, "Fake", 0});
440+
}
441+
442+
std::vector<InputChannelInfo> infos{1};
443+
TimesliceIndex index{1, infos};
444+
auto ref = services.ref();
445+
ref.registerService(ServiceRegistryHelpers::handleForService<TimesliceIndex>(&index));
446+
447+
auto policy = CompletionPolicyHelpers::consumeWhenAll();
448+
DataRelayer relayer(policy, inputs, index, ref, -1);
449+
relayer.setPipelineLength(1);
450+
451+
auto transport = fair::mq::TransportFactory::CreateTransportFactory("zeromq");
452+
453+
// One message pair per input, recycled through the relayer every iteration.
454+
std::vector<fair::mq::MessagePtr> inflight;
455+
inflight.reserve(2 * nInputs);
456+
for (size_t i = 0; i < nInputs; ++i) {
457+
Stack stack{prototypes[i], DataProcessingHeader{0, 1}};
458+
fair::mq::MessagePtr header = transport->CreateMessage(stack.size());
459+
memcpy(header->GetData(), stack.data(), stack.size());
460+
inflight.emplace_back(std::move(header));
461+
inflight.emplace_back(transport->CreateMessage(prototypes[i].payloadSize));
462+
}
463+
464+
for (auto _ : state) {
465+
for (size_t i = 0; i < nInputs; ++i) {
466+
DataRelayer::InputInfo info{0, 2, DataRelayer::InputType::Data, {ChannelIndex::INVALID}};
467+
relayer.relay(inflight[2 * i]->GetData(), &inflight[2 * i], info, 2);
468+
}
469+
std::vector<RecordAction> ready;
470+
relayer.getReadyToProcess(ready);
471+
assert(ready.size() == 1);
472+
auto result = relayer.consumeAllInputsForTimeslice(ready[0].slot);
473+
inflight.clear();
474+
for (size_t i = 0; i < nInputs; ++i) {
475+
for (auto& msg : result[i]) {
476+
inflight.emplace_back(std::move(msg));
477+
}
478+
}
479+
}
480+
}
481+
482+
BENCHMARK(BM_RelayManyInputs)->Arg(1)->Arg(8)->Arg(32)->Arg(128);
483+
405484
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)