Line data Source code
1 : /**
2 : * @file performance.cxx - test the performance of the logger interface
3 : *
4 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
5 : * Licensing/copyright details are in the COPYING file that you should have
6 : * received with this code.
7 : */
8 :
9 : const char *usage = R"foo(
10 : usage: %s [option] # demonstrate threading issues
11 : example: %s
12 : options:
13 : --help, -h - print this help
14 : --loops, -l - loops each thread
15 : --threads, -t - threads in addition to main
16 : --do-issue, -i - use issue
17 : )foo""\n";
18 : #define USAGE() printf( usage, basename(argv[0]), basename(argv[0]) )
19 :
20 : #include <getopt.h> // getopt_long
21 : #include <vector>
22 : #include <thread>
23 : #include <logging/Logging.hpp>
24 :
25 :
26 0 : ERS_DECLARE_ISSUE(ERS_EMPTY, // namespace ERS_EMPTY ==> anonymous
27 : TestIssue, // issue class name
28 : "Three arg TestIssue - arg 1: " << arg1 << " arg 2: " << arg2 << " arg 3: " << arg3,
29 : ((size_t)arg1) ((int)arg2) ((int)arg3)
30 : )
31 :
32 :
33 : static int g_dbglvl=6;
34 : static int g_loops=2;
35 : static int g_do_issue=0;
36 :
37 0 : void thread_func( volatile const int *spinlock, size_t thread_idx )
38 : {
39 0 : int lcllvl = g_dbglvl+thread_idx+1;
40 :
41 0 : while(*spinlock); // The main program thread will clear this
42 : // once all thread are created and given a
43 : // chance to get here.
44 0 : if (g_do_issue) {
45 0 : for (auto uu=0; uu<g_loops; ++uu)
46 0 : ers::debug( TestIssue( ERS_HERE, thread_idx, lcllvl, uu ), lcllvl );
47 : } else {
48 0 : for (auto uu=0; uu<g_loops; ++uu)
49 0 : TLOG_DEBUG(lcllvl) << "tidx " << thread_idx << " fast LOG_DEBUG(" << lcllvl << ") #" <<uu;
50 : }
51 :
52 0 : pthread_exit(nullptr);
53 : }
54 :
55 :
56 0 : int main(int argc, char *argv[])
57 : {
58 0 : dunedaq::logging::Logging::setup("test", "performance"); // either do this or export DUNEDAQ_ERS_FATAL=erstrace,lstderr DUNEDAQ_ERS_ERROR='erstrace,throttle(30,100),lstderr' DUNEDAQ_ERS_WARNING='erstrace,throttle(30,100),lstderr'
59 :
60 0 : int num_threads = 2;
61 0 : int opt_help=0;
62 0 : while (true) {
63 0 : static struct option long_options[] = {
64 : { "help", no_argument, nullptr, 'h' },
65 : { "loops", required_argument, nullptr, 'l' },
66 : { "threads", required_argument, nullptr, 't' },
67 : { "do-issue", no_argument, nullptr, 'i' },
68 : { nullptr, 0, nullptr, 0 }
69 : };
70 0 : int opt = getopt_long( argc, argv, "?hil:t:x",long_options, nullptr );
71 0 : if (opt == -1) break;
72 0 : switch (opt) {
73 : case '?': case 'h': opt_help =1; break;
74 0 : case 'l': g_loops =static_cast<int>(strtoul(optarg,nullptr,0));break;
75 0 : case 't': num_threads=static_cast<int>(strtoul(optarg,nullptr,0));break;
76 0 : case 'i': g_do_issue=1; break;
77 0 : default:
78 0 : TLOG() << "?? getopt returned character code 0" << std::oct << opt;
79 0 : opt_help=1;
80 : }
81 0 : }
82 0 : if (opt_help) { USAGE(); exit(0); }
83 :
84 0 : std::vector<std::thread> threads(num_threads);
85 0 : int spinlock=1;
86 0 : for (size_t ss=0; ss<threads.size(); ++ss)
87 0 : threads[ss] = std::thread(thread_func,&spinlock,ss);
88 :
89 0 : usleep(20000);
90 0 : spinlock = 0;
91 0 : if (g_do_issue) {
92 0 : for (int ii=0; ii<g_loops; ++ii)
93 0 : ers::info( TestIssue( ERS_HERE, 0, g_dbglvl, ii ) );
94 : } else {
95 0 : for (int ii=0; ii<g_loops; ++ii)
96 0 : TLOG_DEBUG(g_dbglvl) << "hello from DEBUG_" << g_dbglvl << " loop " << ii;
97 : }
98 :
99 0 : for (std::thread& tt : threads)
100 0 : tt.join();
101 0 : return (0);
102 : } // main
|