24 #include "application.hh" 28 #include <boost/filesystem.hpp> 32 #include <condition_variable> 41 LOGGER(
mlog,
"M3WriteSpeedTest" );
43 int main(
int argc,
char** argv )
45 scarab::main_app theMain;
47 theMain.default_config().add(
"multithreaded",
new scarab::param_value(
false ) );
48 theMain.default_config().add(
"n-records",
new scarab::param_value( 10000U ) );
49 theMain.default_config().add(
"n-streams",
new scarab::param_value( 1U ) );
50 theMain.default_config().add(
"array-size",
new scarab::param_value( 1024U ) );
51 theMain.default_config().add(
"data-type-size",
new scarab::param_value( 1U ) );
53 theMain.add_config_option< std::string >(
"Filename",
"filename",
"Test output filename" );
54 theMain.add_config_flag<
bool >(
"-m,--multithreaded",
"multithreaded",
"Use multithreaded write" );
55 theMain.add_config_option<
unsigned >(
"-n,--n-records",
"n-records",
"Number of records to write" );
56 theMain.add_config_option<
unsigned >(
"-N,--n-streams",
"n-streams",
"Number of streams to write" );
57 theMain.add_config_option<
unsigned >(
"-a,--array-size",
"array-size",
"Array size" );
58 theMain.add_config_option<
unsigned >(
"-d,--data-type-size",
"data-type-size",
"Data-type size" );
60 CLI11_PARSE( theMain, argc, argv );
64 bool tMultithreaded = theMain.primary_config()[
"multithreaded" ]().as_bool();
65 unsigned tNRecords = theMain.primary_config()[
"n-records" ]().as_uint();
66 unsigned tNStreams = theMain.primary_config()[
"n-streams" ]().as_uint();
67 unsigned tArraySize = theMain.primary_config()[
"array-size" ]().as_uint();
68 unsigned tSampleSize = 1;
69 unsigned tDataTypeSize = theMain.primary_config()[
"data-type-size" ]().as_uint();
71 double tMBToWrite = (double)(tNRecords * tNStreams * tArraySize * tSampleSize * tDataTypeSize) * 10.e-6;
75 LERROR(
mlog,
"Please specify a number of streams > 0" );
80 boost::filesystem::path tFilePath = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
82 LINFO(
mlog,
"Temp file is " << tFilePath );
84 LINFO(
mlog,
"Preparing header" );
85 M3Header* tHeader = tWriteTest->GetHeader();
86 tHeader->Filename() =
"tempfile";
87 tHeader->SetRunDuration( 8675309 );
88 tHeader->Timestamp( ) =
"Stardate 33515";
89 tHeader->Description() =
"Bigger on the inside";
91 LINFO(
mlog,
"Adding stream(s)" );
93 std::vector< unsigned > tStreamNums( tNStreams );
94 for(
unsigned iStream = 0; iStream < tNStreams; ++iStream )
96 std::stringstream tStr;
97 tStr <<
"Channel " << iStream;
99 tStreamNums[ iStream ] = tSingleStreamNum;
102 tWriteTest->WriteHeader();
104 LINFO(
mlog,
"Wrote header:\n" << *tHeader );
107 LINFO(
mlog,
"Creating fake data array" );
109 unsigned tNBytes = tArraySize * tDataTypeSize * tSampleSize;
110 std::vector< byte_type > tDataMaster( tNBytes );
113 for(
unsigned iBin = 0; iBin < tArraySize; ++iBin )
115 tDMWriter.
set_at( 42, iBin );
119 LINFO(
mlog,
"Getting stream pointers" );
121 std::vector< M3Stream* > tStreams( tNStreams );
122 std::vector< byte_type* > tStreamData( tNStreams );
123 for(
unsigned iStream = 0; iStream < tNStreams; ++iStream )
125 tStreams[ iStream ] = tWriteTest->GetStream( tStreamNums[ iStream ] );
126 tStreamData[ iStream ] = tStreams[ iStream ]->GetStreamRecord()->GetData();
129 LINFO(
mlog,
"Writing data" );
131 using std::chrono::steady_clock;
132 using std::chrono::duration;
133 using std::chrono::duration_cast;
138 std::mutex tRunMutex;
139 std::condition_variable tRunRelease;
141 std::vector< std::thread > tThreads;
142 std::atomic< unsigned > tNThreadsReady( 0 );
144 for(
unsigned iStream = 0; iStream < tNStreams; ++iStream )
146 tThreads.push_back( std::thread( [&, iStream]{
148 bool tIsNewAcq =
true;
149 std::unique_lock< std::mutex > tRunLock( tRunMutex );
151 tRunRelease.wait( tRunLock );
152 for(
unsigned iRecord = 0; iRecord < tNRecords; ++iRecord )
154 ::memcpy( tStreamData[ iStream ], tDataMaster.data(), tNBytes );
155 if( ! tStreams[ iStream ]->WriteRecord( tIsNewAcq ) )
157 LERROR(
mlog,
"Unable to write record <" << iRecord <<
"> for stream <" << iStream <<
">" );
167 LINFO(
mlog,
"Waiting for threads to be ready" );
168 while( tNThreadsReady.load() != tNStreams )
170 std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
172 std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
174 LINFO(
mlog,
"Releasing threads" );
175 tRunRelease.notify_all();
177 steady_clock::time_point tStartTime = steady_clock::now();
179 for(
unsigned iStream = 0; iStream < tNStreams; ++iStream )
181 tThreads[ iStream ].join();
184 steady_clock::time_point tEndTime = steady_clock::now();
186 duration< double > tDuration = duration_cast< duration< double > >( tEndTime - tStartTime );
188 LINFO(
mlog,
"Processing time: " << tDuration.count() <<
" sec" );
189 LINFO(
mlog,
"Size of data written: " << tMBToWrite <<
" MB" );
190 LINFO(
mlog,
"Write speed: " << tMBToWrite / tDuration.count() <<
" MB/s" );
196 bool tIsNewAcq =
true;
198 steady_clock::time_point tStartTime = steady_clock::now();
200 for(
unsigned iRecord = 0; iRecord < tNRecords; ++iRecord )
202 for(
unsigned iStream = 0; iStream < tNStreams; ++iStream )
204 ::memcpy( tStreamData[ iStream ], tDataMaster.data(), tNBytes );
205 if( ! tStreams[ iStream ]->WriteRecord( tIsNewAcq ) )
207 LERROR(
mlog,
"Unable to write record <" << iRecord <<
"> for stream <" << iStream <<
">" );
214 steady_clock::time_point tEndTime = steady_clock::now();
216 duration< double > tDuration = duration_cast< duration< double > >( tEndTime - tStartTime );
218 LINFO(
mlog,
"Processing time: " << tDuration.count() <<
" sec" );
219 LINFO(
mlog,
"Size of data written: " << tMBToWrite <<
" MB" );
220 LINFO(
mlog,
"Write speed: " << tMBToWrite / tDuration.count() <<
" MB/s" );
224 LINFO(
mlog,
"Closing file" );
226 tWriteTest->FinishWriting();
228 boost::filesystem::remove( tFilePath );
230 LINFO(
mlog,
"Test finished" );
233 catch( std::exception& e )
235 LERROR(
mlog,
"Exception thrown during write-speed test:\n" << e.what() );
239 return RETURN_SUCCESS;
static const uint32_t sDigitizedUS
void set_at(SetType value, unsigned index)
static scarab::logger mlog("M3Header")
Interface class for a variety of data types.
int main(int argc, char **argv)
static const uint32_t sBitsAlignedLeft
static Monarch3 * OpenForWriting(const std::string &filename)