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 <stdlib.h> // rand_r, RAND_MAX
22 : #include <vector>
23 : #include <thread>
24 : #define JUST_ERS 0
25 : #if JUST_ERS
26 : # include <ers/ers.hpp>
27 : #else
28 : # include <logging/Logging.hpp>
29 : #endif
30 :
31 :
32 0 : ERS_DECLARE_ISSUE(ERS_EMPTY, // namespace ERS_EMPTY ==> anonymous
33 : TestIssue, // issue class name
34 : "Three arg TestIssue - arg 1: " << arg1 << " arg 2: " << arg2 << " arg 3: " << arg3,
35 : ((size_t)arg1) ((int)arg2) ((int)arg3)
36 : )
37 :
38 :
39 : static int g_dbglvl=6;
40 : static int g_loops=2;
41 : static int g_do_issue=0;
42 :
43 0 : void thread_func( volatile const int *spinlock, size_t thread_idx )
44 : {
45 0 : int lcllvl = g_dbglvl+thread_idx+1;
46 :
47 0 : unsigned seed=1;
48 0 : unsigned *seedp=&seed;
49 :
50 0 : while(*spinlock); // The main program thread will clear this
51 : // once all thread are created and given a
52 : // chance to get here.
53 0 : for (auto uu=0; uu<g_loops; ++uu) {
54 0 : unsigned rr=rand_r(seedp);
55 0 : if (rr < RAND_MAX/2)
56 0 : ers::warning( TestIssue( ERS_HERE, thread_idx, lcllvl, uu ) );
57 0 : else if (g_do_issue)
58 : # if JUST_ERS
59 : ers::log( TestIssue( ERS_HERE, thread_idx, lcllvl, uu ) );
60 : # else
61 0 : TLOG() << TestIssue( ERS_HERE, thread_idx, lcllvl, uu );
62 : else
63 0 : TLOG() << "thread_idx=" << thread_idx << " uu=" << uu;
64 : # endif
65 : }
66 :
67 0 : pthread_exit(nullptr);
68 : }
69 :
70 :
71 0 : int main(int argc, char *argv[])
72 : {
73 : # if JUST_ERS == 0
74 0 : dunedaq::logging::Logging::setup("test", "multithreaded_warning_log"); // 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'
75 : # endif
76 :
77 0 : int num_threads = 20;
78 0 : int opt_help=0;
79 0 : while (true) {
80 0 : static struct option long_options[] = {
81 : { "help", no_argument, nullptr, 'h' },
82 : { "loops", required_argument, nullptr, 'l' },
83 : { "threads", required_argument, nullptr, 't' },
84 : { "do-issue", no_argument, nullptr, 'i' },
85 : { nullptr, 0, nullptr, 0 }
86 : };
87 0 : int opt = getopt_long( argc, argv, "?hil:t:x",long_options, nullptr );
88 0 : if (opt == -1) break;
89 0 : switch (opt) {
90 : case '?': case 'h': opt_help =1; break;
91 0 : case 'l': g_loops =static_cast<int>(strtoul(optarg,nullptr,0));break;
92 0 : case 't': num_threads=static_cast<int>(strtoul(optarg,nullptr,0));break;
93 0 : case 'i': g_do_issue=1; break;
94 0 : default:
95 : # if JUST_ERS == 0
96 0 : TLOG() << "?? getopt returned character code 0" << std::oct << opt;
97 : # endif
98 0 : opt_help=1;
99 : }
100 0 : }
101 0 : if (opt_help) { USAGE(); exit(0); }
102 :
103 0 : unsigned seed=1;
104 0 : unsigned *seedp=&seed;
105 :
106 0 : std::vector<std::thread> threads(num_threads);
107 0 : int spinlock=1;
108 0 : for (size_t ss=0; ss<threads.size(); ++ss)
109 0 : threads[ss] = std::thread(thread_func,&spinlock,ss);
110 :
111 0 : usleep(20000);
112 0 : spinlock = 0;
113 0 : for (auto uu=0; uu<g_loops; ++uu) {
114 0 : unsigned rr=rand_r(seedp);
115 0 : if (rr < RAND_MAX/2)
116 0 : ers::warning( TestIssue( ERS_HERE, 999, 998, uu ) );
117 0 : else if (g_do_issue)
118 : # if JUST_ERS
119 : ers::log( TestIssue( ERS_HERE, 999, 998, uu ) );
120 : # else
121 0 : TLOG() << TestIssue( ERS_HERE, 999, 998, uu );
122 : else
123 0 : TLOG() << " uu=" << uu;
124 : # endif
125 : }
126 :
127 0 : for (std::thread& tt : threads)
128 0 : tt.join();
129 0 : return (0);
130 : } // main
|