1 #define TRACE_NAME "GenToBuffer"
3 #include <boost/program_options.hpp>
4 #include <boost/thread.hpp>
6 #include "fhiclcpp/ParameterSet.h"
7 namespace bpo = boost::program_options;
9 #include "artdaq-core/Utilities/configureMessageFacility.hh"
10 #include "artdaq/Application/LoadParameterSet.hh"
11 #include "artdaq/DAQrate/FragmentBuffer.hh"
12 #include "artdaq/DAQrate/RequestBuffer.hh"
13 #include "artdaq/Generators/CommandableFragmentGenerator.hh"
14 #include "artdaq/Generators/makeCommandableFragmentGenerator.hh"
28 : generator_ptr_(nullptr)
35 generator_ptr_->SetRequestBuffer(request_buffer_ptr_);
36 fragment_buffer_ptr_->SetRequestBuffer(request_buffer_ptr_);
45 metricMan->do_start();
46 request_buffer_ptr_->setRunning(
true);
47 generator_ptr_->StartCmd(run_number, 0, 0);
50 boost::thread::attributes attrs;
51 attrs.set_stack_size(4096 * 2000);
52 receive_thread_.reset(
new boost::thread(attrs, boost::bind(&GenToBufferTest::receive_fragments,
this)));
53 send_thread_.reset(
new boost::thread(attrs, boost::bind(&GenToBufferTest::send_fragments,
this)));
60 generator_ptr_->StopCmd(0, 0);
61 fragment_buffer_ptr_->Stop();
62 request_buffer_ptr_->setRunning(
false);
65 if (receive_thread_ && receive_thread_->joinable()) receive_thread_->join();
66 if (send_thread_ && send_thread_->joinable()) send_thread_->join();
77 void receive_fragments()
79 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
80 artdaq::FragmentPtrs frags;
84 while (active && running_)
86 auto loop_start = std::chrono::steady_clock::now();
87 TLOG(18) <<
"receive_fragments getNext start";
88 active = generator_ptr_->getNext(frags);
89 TLOG(18) <<
"receive_fragments getNext done (active=" << active <<
")";
90 auto after_getnext = std::chrono::steady_clock::now();
97 if (!active && generator_ptr_ && generator_ptr_->exception())
99 TLOG(TLVL_ERROR) <<
"Generator has an exception, aborting!";
103 if (!active) {
break; }
105 if (frags.size() > 0)
107 metricMan->sendMetric(
"Fragments Generated", frags.size(),
"fragments", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Rate | artdaq::MetricMode::Average);
109 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer start";
110 fragment_buffer_ptr_->AddFragmentsToBuffer(std::move(frags));
111 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer done";
112 auto after_addFragsToBuffer = std::chrono::steady_clock::now();
113 metricMan->sendMetric(
"FragmentBufferAddTime", artdaq::TimeUtils::GetElapsedTime(after_getnext, after_addFragsToBuffer),
"s", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Average | artdaq::MetricMode::Minimum | artdaq::MetricMode::Maximum);
115 metricMan->sendMetric(
"GetNextTime", artdaq::TimeUtils::GetElapsedTime(loop_start, after_getnext),
"s", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Average | artdaq::MetricMode::Minimum | artdaq::MetricMode::Maximum);
119 TLOG(TLVL_DEBUG) <<
"receive_fragments loop end";
122 void send_fragments()
124 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
125 artdaq::FragmentPtrs frags;
129 while (active && running_)
131 auto loop_start = std::chrono::steady_clock::now();
133 TLOG(18) <<
"send_fragments applyRequests start";
134 active = fragment_buffer_ptr_->applyRequests(frags);
135 TLOG(18) <<
"send_fragments applyRequests done (active=" << active <<
")";
137 auto after_requests = std::chrono::steady_clock::now();
138 if (!active) {
break; }
140 for (
auto& fragPtr : frags)
144 TLOG(TLVL_WARNING) <<
"Encountered a bad fragment pointer in fragment " << fragment_count_ <<
". "
145 <<
"This is most likely caused by a problem with the Fragment Generator!";
148 if (fragment_count_ == 0)
150 TLOG(TLVL_DEBUG) <<
"Received first Fragment from Fragment Generator, sequence ID " << fragPtr->sequenceID() <<
", size = " << fragPtr->sizeBytes() <<
" bytes.";
152 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
153 SetMFIteration(
"Sequence ID " + std::to_string(sequence_id));
155 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
159 TLOG(((fragment_count_ == 1) ? TLVL_DEBUG
160 : (((fragment_count_ % 250) == 0) ? 13 : 14)))
161 << ((fragment_count_ == 1)
162 ?
"Sent first Fragment"
163 :
"Sending fragment " + std::to_string(fragment_count_))
164 <<
" with SeqID " << sequence_id <<
".";
167 metricMan->sendMetric(
"Fragments Discarded", frags.size(),
"fragments", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Rate | artdaq::MetricMode::Average);
169 auto after_frag_check = std::chrono::steady_clock::now();
170 metricMan->sendMetric(
"ApplyRequestsTime", artdaq::TimeUtils::GetElapsedTime(loop_start, after_requests),
"s", 3, artdaq::MetricMode::Average | artdaq::MetricMode::Accumulate | artdaq::MetricMode::Maximum | artdaq::MetricMode::Minimum);
171 metricMan->sendMetric(
"FragmentDiscardTime", artdaq::TimeUtils::GetElapsedTime(after_requests, after_frag_check),
"s", 3, artdaq::MetricMode::Average | artdaq::MetricMode::Accumulate);
173 std::this_thread::yield();
179 metricMan->do_stop();
181 TLOG(TLVL_DEBUG) <<
"send_fragments loop end";
185 std::unique_ptr<CommandableFragmentGenerator> generator_ptr_;
186 std::unique_ptr<FragmentBuffer> fragment_buffer_ptr_;
187 std::shared_ptr<RequestBuffer> request_buffer_ptr_;
188 std::atomic<size_t> fragment_count_;
189 std::atomic<bool> running_;
190 std::unique_ptr<boost::thread> receive_thread_;
191 std::unique_ptr<boost::thread> send_thread_;
195 int main(
int argc,
char* argv[])
197 artdaq::configureMessageFacility(
"RequestSender");
199 struct FragmentReceiverConfig
201 fhicl::TableFragment<artdaq::CommandableFragmentGenerator::Config> generatorConfig;
202 fhicl::TableFragment<artdaq::FragmentBuffer::Config> fragmentBufferConfig;
207 fhicl::Table<FragmentReceiverConfig> frConfig{fhicl::Name{
"fragment_receiver"}};
212 fhicl::Table<DAQConfig> daq{fhicl::Name{
"daq"}};
213 fhicl::Table<artdaq::MetricManager::Config> metrics{fhicl::Name{
"metrics"}};
214 fhicl::Atom<double> test_duration_s{fhicl::Name{
"test_duration_s"}, fhicl::Comment{
"Duration, in seconds, for the test"}, 60.0};
215 fhicl::Atom<size_t> time_between_requests_us{fhicl::Name{
"time_between_requests_us"}, fhicl::Comment{
"Amount of time to wait between generated requests, in us"}, 1000};
216 fhicl::Atom<artdaq::Fragment::timestamp_t> timestamp_increment{fhicl::Name{
"timestamp_increment"}, fhicl::Comment{
"Amount to increment the timestamp for each request"}, 1};
217 fhicl::Atom<int> run_number{fhicl::Name{
"run_number"}, fhicl::Comment{
"Run Number to use for the test"}, 101};
220 auto pset = LoadParameterSet<Config>(argc, argv,
"GenToBuffer",
"This test application evaluates the rate of Fragment Generation and Request Application.");
223 metricMan->initialize(pset.get<fhicl::ParameterSet>(
"metrics", fhicl::ParameterSet()),
"GenToBuffer");
225 if (pset.has_key(
"daq"))
227 fr_pset = pset.get<fhicl::ParameterSet>(
"daq");
230 if (fr_pset.has_key(
"fragment_receiver"))
232 fr_pset = fr_pset.get<fhicl::ParameterSet>(
"fragment_receiver");
236 auto buf = gtbt.GetRequestBuffer();
238 auto start_time = std::chrono::steady_clock::now();
239 auto duration = pset.get<
double>(
"test_duration_s", 60);
240 artdaq::Fragment::sequence_id_t seq = 0;
241 artdaq::Fragment::timestamp_t timestamp = 1;
242 auto time_between_requests_us = pset.get<
size_t>(
"time_between_requests_us", 1000);
243 auto timestamp_scale = pset.get<artdaq::Fragment::timestamp_t>(
"timestamp_increment", 1);
245 gtbt.start(pset.get<
int>(
"run_number", 101));
247 while (artdaq::TimeUtils::GetElapsedTime(start_time) < duration)
249 buf->push(++seq, timestamp);
250 timestamp += timestamp_scale;
252 auto us_since_start = artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time);
253 int64_t time_diff = seq * time_between_requests_us - us_since_start;
254 TLOG(40) <<
"Time Diff: " << time_diff <<
", Time since start: " << us_since_start <<
", current epoch: " << seq * time_between_requests_us;
Test fixture for GenToBuffer_t.
std::shared_ptr< RequestBuffer > GetRequestBuffer()
Get a handle to the RequestBuffer.
Configuration for simple_metric_sender.
void start(int run_number)
Start the test fixture.
std::unique_ptr< CommandableFragmentGenerator > makeCommandableFragmentGenerator(std::string const &generator_plugin_spec, fhicl::ParameterSet const &ps)
Load a CommandableFragmentGenerator plugin.
FragmentBuffer is a FragmentGenerator-derived abstract class that defines the interface for a Fragmen...
Holds requests from RequestReceiver while they are being processed.
void stop()
Stop the test fixture.
GenToBufferTest(fhicl::ParameterSet const &ps)
GenToBufferTest constructor.