1 #define TRACE_NAME "GenToBuffer"
3 #include <boost/program_options.hpp>
4 #include <boost/thread.hpp>
6 #include "fhiclcpp/make_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"
21 : generator_ptr_(
nullptr)
28 generator_ptr_->SetRequestBuffer(request_buffer_ptr_);
29 fragment_buffer_ptr_->SetRequestBuffer(request_buffer_ptr_);
32 void start(
int run_number)
34 metricMan->do_start();
35 request_buffer_ptr_->setRunning(
true);
36 generator_ptr_->StartCmd(run_number, 0, 0);
39 boost::thread::attributes attrs;
40 attrs.set_stack_size(4096 * 2000);
41 receive_thread_.reset(
new boost::thread(attrs, boost::bind(&GenToBufferTest::receive_fragments,
this)));
42 send_thread_.reset(
new boost::thread(attrs, boost::bind(&GenToBufferTest::send_fragments,
this)));
46 generator_ptr_->StopCmd(0, 0);
47 fragment_buffer_ptr_->Stop();
48 request_buffer_ptr_->setRunning(
false);
51 if (receive_thread_ && receive_thread_->joinable()) receive_thread_->join();
52 if (send_thread_ && send_thread_->joinable()) send_thread_->join();
56 std::shared_ptr<RequestBuffer> GetRequestBuffer() {
return request_buffer_ptr_; }
59 void receive_fragments()
61 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
62 artdaq::FragmentPtrs frags;
66 while (active && running_)
68 auto loop_start = std::chrono::steady_clock::now();
69 TLOG(18) <<
"receive_fragments getNext start";
70 active = generator_ptr_->getNext(frags);
71 TLOG(18) <<
"receive_fragments getNext done (active=" << active <<
")";
72 auto after_getnext = std::chrono::steady_clock::now();
79 if (!active && generator_ptr_ && generator_ptr_->exception())
81 TLOG(TLVL_ERROR) <<
"Generator has an exception, aborting!";
85 if (!active) {
break; }
89 metricMan->sendMetric(
"Fragments Generated", frags.size(),
"fragments", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Rate | artdaq::MetricMode::Average);
91 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer start";
92 fragment_buffer_ptr_->AddFragmentsToBuffer(std::move(frags));
93 TLOG(18) <<
"receive_fragments AddFragmentsToBuffer done";
94 auto after_addFragsToBuffer = std::chrono::steady_clock::now();
95 metricMan->sendMetric(
"FragmentBufferAddTime", artdaq::TimeUtils::GetElapsedTime(after_getnext, after_addFragsToBuffer),
"s", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Average | artdaq::MetricMode::Minimum | artdaq::MetricMode::Maximum);
97 metricMan->sendMetric(
"GetNextTime", artdaq::TimeUtils::GetElapsedTime(loop_start, after_getnext),
"s", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Average | artdaq::MetricMode::Minimum | artdaq::MetricMode::Maximum);
101 TLOG(TLVL_DEBUG) <<
"receive_fragments loop end";
104 void send_fragments()
106 TLOG(TLVL_DEBUG) <<
"Waiting for first fragment.";
107 artdaq::FragmentPtrs frags;
111 while (active && running_)
113 auto loop_start = std::chrono::steady_clock::now();
115 TLOG(18) <<
"send_fragments applyRequests start";
116 active = fragment_buffer_ptr_->applyRequests(frags);
117 TLOG(18) <<
"send_fragments applyRequests done (active=" << active <<
")";
119 auto after_requests = std::chrono::steady_clock::now();
120 if (!active) {
break; }
122 for (
auto& fragPtr : frags)
126 TLOG(TLVL_WARNING) <<
"Encountered a bad fragment pointer in fragment " << fragment_count_ <<
". "
127 <<
"This is most likely caused by a problem with the Fragment Generator!";
130 if (fragment_count_ == 0)
132 TLOG(TLVL_DEBUG) <<
"Received first Fragment from Fragment Generator, sequence ID " << fragPtr->sequenceID() <<
", size = " << fragPtr->sizeBytes() <<
" bytes.";
134 artdaq::Fragment::sequence_id_t sequence_id = fragPtr->sequenceID();
135 SetMFIteration(
"Sequence ID " + std::to_string(sequence_id));
137 TLOG(17) <<
"send_fragments seq=" << sequence_id <<
" sendFragment start";
141 TLOG(((fragment_count_ == 1) ? TLVL_DEBUG
142 : (((fragment_count_ % 250) == 0) ? 13 : 14)))
143 << ((fragment_count_ == 1)
144 ?
"Sent first Fragment"
145 :
"Sending fragment " + std::to_string(fragment_count_))
146 <<
" with SeqID " << sequence_id <<
".";
149 metricMan->sendMetric(
"Fragments Discarded", frags.size(),
"fragments", 3, artdaq::MetricMode::Accumulate | artdaq::MetricMode::Rate | artdaq::MetricMode::Average);
151 auto after_frag_check = std::chrono::steady_clock::now();
152 metricMan->sendMetric(
"ApplyRequestsTime", artdaq::TimeUtils::GetElapsedTime(loop_start, after_requests),
"s", 3, artdaq::MetricMode::Average | artdaq::MetricMode::Accumulate|artdaq::MetricMode::Maximum|artdaq::MetricMode::Minimum);
153 metricMan->sendMetric(
"FragmentDiscardTime", artdaq::TimeUtils::GetElapsedTime(after_requests, after_frag_check),
"s", 3, artdaq::MetricMode::Average | artdaq::MetricMode::Accumulate);
155 std::this_thread::yield();
161 metricMan->do_stop();
163 TLOG(TLVL_DEBUG) <<
"send_fragments loop end";
167 std::unique_ptr<CommandableFragmentGenerator> generator_ptr_;
168 std::unique_ptr<FragmentBuffer> fragment_buffer_ptr_;
169 std::shared_ptr<RequestBuffer> request_buffer_ptr_;
170 std::atomic<size_t> fragment_count_;
171 std::atomic<bool> running_;
172 std::unique_ptr<boost::thread> receive_thread_;
173 std::unique_ptr<boost::thread> send_thread_;
177 int main(
int argc,
char* argv[])
179 artdaq::configureMessageFacility(
"RequestSender");
181 struct FragmentReceiverConfig
183 fhicl::TableFragment<artdaq::CommandableFragmentGenerator::Config> generatorConfig;
184 fhicl::TableFragment<artdaq::FragmentBuffer::Config> fragmentBufferConfig;
189 fhicl::Table<FragmentReceiverConfig> frConfig{fhicl::Name{
"fragment_receiver"}};
194 fhicl::Table<DAQConfig> daq{fhicl::Name{
"daq"}};
195 fhicl::Table<artdaq::MetricManager::Config> metrics{fhicl::Name{
"metrics"}};
196 fhicl::Atom<double> test_duration_s{fhicl::Name{
"test_duration_s"}, fhicl::Comment{
"Duration, in seconds, for the test"}, 60.0};
197 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};
198 fhicl::Atom<artdaq::Fragment::timestamp_t> timestamp_increment{fhicl::Name{
"timestamp_increment"}, fhicl::Comment{
"Amount to increment the timestamp for each request"}, 1};
199 fhicl::Atom<int> run_number{fhicl::Name{
"run_number"}, fhicl::Comment{
"Run Number to use for the test"}, 101};
202 auto pset = LoadParameterSet<Config>(argc, argv,
"GenToBuffer",
"This test application evaluates the rate of Fragment Generation and Request Application.");
205 metricMan->initialize(pset.get<fhicl::ParameterSet>(
"metrics", fhicl::ParameterSet()),
"GenToBuffer");
207 if (pset.has_key(
"daq"))
209 fr_pset = pset.get<fhicl::ParameterSet>(
"daq");
212 if (fr_pset.has_key(
"fragment_receiver"))
214 fr_pset = fr_pset.get<fhicl::ParameterSet>(
"fragment_receiver");
218 auto buf = gtbt.GetRequestBuffer();
220 auto start_time = std::chrono::steady_clock::now();
221 auto duration = pset.get<
double>(
"test_duration_s", 60);
222 artdaq::Fragment::sequence_id_t seq = 0;
223 artdaq::Fragment::timestamp_t timestamp = 1;
224 auto time_between_requests_us = pset.get<
size_t>(
"time_between_requests_us", 1000);
225 auto timestamp_scale = pset.get<artdaq::Fragment::timestamp_t>(
"timestamp_increment", 1);
227 gtbt.start(pset.get<
int>(
"run_number", 101));
229 while (artdaq::TimeUtils::GetElapsedTime(start_time) < duration)
231 buf->push(++seq, timestamp);
232 timestamp += timestamp_scale;
234 auto us_since_start = artdaq::TimeUtils::GetElapsedTimeMicroseconds(start_time);
235 int64_t time_diff = seq * time_between_requests_us - us_since_start;
236 TLOG(40) <<
"Time Diff: " << time_diff <<
", Time since start: " << us_since_start <<
", current epoch: " << seq * time_between_requests_us;
237 if (time_diff > 10) {
Configuration for simple_metric_sender.
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...