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 <logging/Logging.hpp>
23 : #include <thread>
24 : #include <vector>
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 : static int g_dbglvl = 6;
32 : static int g_loops = 2;
33 : static int g_do_issue = 0;
34 :
35 : void
36 0 : thread_func(volatile const int* spinlock, size_t thread_idx)
37 : {
38 0 : int lcllvl = g_dbglvl + thread_idx + 1;
39 :
40 0 : while (*spinlock)
41 : ; // 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 : int
56 0 : main(int argc, char* argv[])
57 : {
58 0 : dunedaq::logging::Logging::setup("test",
59 : "performance"); // either do this or export DUNEDAQ_ERS_FATAL=erstrace,lstderr
60 : // DUNEDAQ_ERS_ERROR='erstrace,throttle(30,100),lstderr'
61 : // DUNEDAQ_ERS_WARNING='erstrace,throttle(30,100),lstderr'
62 :
63 0 : int num_threads = 2;
64 0 : int opt_help = 0;
65 0 : while (true) {
66 0 : static struct option long_options[] = { { "help", no_argument, nullptr, 'h' },
67 : { "loops", required_argument, nullptr, 'l' },
68 : { "threads", required_argument, nullptr, 't' },
69 : { "do-issue", no_argument, nullptr, 'i' },
70 : { nullptr, 0, nullptr, 0 } };
71 0 : int opt = getopt_long(argc, argv, "?hil:t:x", long_options, nullptr);
72 0 : if (opt == -1)
73 : break;
74 0 : switch (opt) {
75 : case '?':
76 : case 'h':
77 : opt_help = 1;
78 : break;
79 0 : case 'l':
80 0 : g_loops = static_cast<int>(strtoul(optarg, nullptr, 0));
81 0 : break;
82 0 : case 't':
83 0 : num_threads = static_cast<int>(strtoul(optarg, nullptr, 0));
84 0 : break;
85 0 : case 'i':
86 0 : g_do_issue = 1;
87 0 : break;
88 0 : default:
89 0 : TLOG() << "?? getopt returned character code 0" << std::oct << opt;
90 0 : opt_help = 1;
91 : }
92 0 : }
93 0 : if (opt_help) {
94 0 : USAGE();
95 0 : exit(0);
96 : }
97 :
98 0 : std::vector<std::thread> threads(num_threads);
99 0 : int spinlock = 1;
100 0 : for (size_t ss = 0; ss < threads.size(); ++ss)
101 0 : threads[ss] = std::thread(thread_func, &spinlock, ss);
102 :
103 0 : usleep(20000);
104 0 : spinlock = 0;
105 0 : if (g_do_issue) {
106 0 : for (int ii = 0; ii < g_loops; ++ii)
107 0 : ers::info(TestIssue(ERS_HERE, 0, g_dbglvl, ii));
108 : } else {
109 0 : for (int ii = 0; ii < g_loops; ++ii)
110 0 : TLOG_DEBUG(g_dbglvl) << "hello from DEBUG_" << g_dbglvl << " loop " << ii;
111 : }
112 :
113 0 : for (std::thread& tt : threads)
114 0 : tt.join();
115 0 : return (0);
116 : } // main
|