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"
18 : "\n";
19 : #define USAGE() printf(usage, basename(argv[0]), basename(argv[0]))
20 :
21 : #include <getopt.h> // getopt_long
22 : #include <stdlib.h> // rand_r, RAND_MAX
23 : #include <thread>
24 : #include <vector>
25 : #define JUST_ERS 0
26 : #if JUST_ERS
27 : #include <ers/ers.hpp>
28 : #else
29 : #include <logging/Logging.hpp>
30 : #endif
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 : static int g_dbglvl = 6;
38 : static int g_loops = 2;
39 : static int g_do_issue = 0;
40 :
41 : void
42 0 : thread_func(volatile const int* spinlock, size_t thread_idx)
43 : {
44 0 : int lcllvl = g_dbglvl + thread_idx + 1;
45 :
46 0 : unsigned seed = 1;
47 0 : unsigned* seedp = &seed;
48 :
49 0 : while (*spinlock)
50 : ; // 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 : int
71 0 : main(int argc, char* argv[])
72 : {
73 : #if JUST_ERS == 0
74 0 : dunedaq::logging::Logging::setup(
75 : "test", "multithreaded_warning_log"); // either do this or export DUNEDAQ_ERS_FATAL=erstrace,lstderr
76 : // DUNEDAQ_ERS_ERROR='erstrace,throttle(30,100),lstderr'
77 : // DUNEDAQ_ERS_WARNING='erstrace,throttle(30,100),lstderr'
78 : #endif
79 :
80 0 : int num_threads = 20;
81 0 : int opt_help = 0;
82 0 : while (true) {
83 0 : static struct option long_options[] = { { "help", no_argument, nullptr, 'h' },
84 : { "loops", required_argument, nullptr, 'l' },
85 : { "threads", required_argument, nullptr, 't' },
86 : { "do-issue", no_argument, nullptr, 'i' },
87 : { nullptr, 0, nullptr, 0 } };
88 0 : int opt = getopt_long(argc, argv, "?hil:t:x", long_options, nullptr);
89 0 : if (opt == -1)
90 : break;
91 0 : switch (opt) {
92 : case '?':
93 : case 'h':
94 : opt_help = 1;
95 : break;
96 0 : case 'l':
97 0 : g_loops = static_cast<int>(strtoul(optarg, nullptr, 0));
98 0 : break;
99 0 : case 't':
100 0 : num_threads = static_cast<int>(strtoul(optarg, nullptr, 0));
101 0 : break;
102 0 : case 'i':
103 0 : g_do_issue = 1;
104 0 : break;
105 0 : default:
106 : #if JUST_ERS == 0
107 0 : TLOG() << "?? getopt returned character code 0" << std::oct << opt;
108 : #endif
109 0 : opt_help = 1;
110 : }
111 0 : }
112 0 : if (opt_help) {
113 0 : USAGE();
114 0 : exit(0);
115 : }
116 :
117 0 : unsigned seed = 1;
118 0 : unsigned* seedp = &seed;
119 :
120 0 : std::vector<std::thread> threads(num_threads);
121 0 : int spinlock = 1;
122 0 : for (size_t ss = 0; ss < threads.size(); ++ss)
123 0 : threads[ss] = std::thread(thread_func, &spinlock, ss);
124 :
125 0 : usleep(20000);
126 0 : spinlock = 0;
127 0 : for (auto uu = 0; uu < g_loops; ++uu) {
128 0 : unsigned rr = rand_r(seedp);
129 0 : if (rr < RAND_MAX / 2)
130 0 : ers::warning(TestIssue(ERS_HERE, 999, 998, uu));
131 0 : else if (g_do_issue)
132 : #if JUST_ERS
133 : ers::log(TestIssue(ERS_HERE, 999, 998, uu));
134 : #else
135 0 : TLOG() << TestIssue(ERS_HERE, 999, 998, uu);
136 : else
137 0 : TLOG() << " uu=" << uu;
138 : #endif
139 : }
140 :
141 0 : for (std::thread& tt : threads)
142 0 : tt.join();
143 0 : return (0);
144 : } // main
|