1 // Copyright (c) 2011 Bryce Lelbach
2 // Copyright (c) 2009-2010 Dylan Stark
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6
7 // #define HPX_USE_WINDOWS_PERFORMANCE_COUNTERS 1
8
9 #include <hpx/hpx_init.hpp>
10 #include <hpx/exception.hpp>
11 #include <hpx/include/performance_counters.hpp>
12 #include <hpx/include/lcos.hpp>
13 #include <hpx/runtime/actions/plain_action.hpp>
14 #include <hpx/runtime/threads/thread_helpers.hpp>
15 #include <hpx/lcos/future.hpp>
16 #include <hpx/state.hpp>
17 #include <hpx/util/format.hpp>
18
19 #include <cstdint>
20 #include <iostream>
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 // include Windows specific performance counter binding
26 #if defined(HPX_WINDOWS) && HPX_USE_WINDOWS_PERFORMANCE_COUNTERS != 0
27 #include "win_perf_counters.hpp"
28 #endif
29
30 ///////////////////////////////////////////////////////////////////////////////
stop_monitor(std::shared_ptr<hpx::promise<void>> p)31 void stop_monitor(std::shared_ptr<hpx::promise<void> > p)
32 {
33 p->set_value(); // Kill the monitor.
34 }
35
36 ///////////////////////////////////////////////////////////////////////////////
monitor(double runfor,std::string const & name,std::uint64_t pause)37 int monitor(double runfor, std::string const& name, std::uint64_t pause)
38 {
39 #if defined(HPX_WINDOWS) && HPX_USE_WINDOWS_PERFORMANCE_COUNTERS != 0
40 hpx::register_shutdown_function(&uninstall_windows_counters);
41 #endif
42
43 // Resolve the GID of the performance counter using it's symbolic name.
44 hpx::naming::id_type id = hpx::performance_counters::get_counter(name);
45 if (!id)
46 {
47 hpx::util::format_to(std::cout,
48 "error: performance counter not found ({})",
49 name) << std::endl;
50 return 1;
51 }
52
53 std::uint32_t const locality_id = hpx::get_locality_id();
54 if (locality_id == hpx::naming::get_locality_id_from_gid(id.get_gid()))
55 {
56 hpx::util::format_to(std::cout,
57 "error: cannot query performance counters on its own locality ({})",
58 name) << std::endl;
59 return 1;
60 }
61
62 std::shared_ptr<hpx::promise<void> > stop_flag =
63 std::make_shared<hpx::promise<void> >();
64 hpx::future<void> f = stop_flag->get_future();
65
66 hpx::register_shutdown_function(
67 hpx::util::bind(&stop_monitor, stop_flag));
68
69 std::int64_t zero_time = 0;
70
71 hpx::util::high_resolution_timer t;
72 while (runfor < 0 || t.elapsed() < runfor)
73 {
74 // stop collecting data when the runtime is exiting
75 if (!hpx::is_running() || f.is_ready())
76 return 0;
77
78 // Query the performance counter.
79 using namespace hpx::performance_counters;
80 counter_value value =
81 stubs::performance_counter::get_value(hpx::launch::sync, id);
82
83 if (status_is_valid(value.status_))
84 {
85 if (!zero_time)
86 zero_time = value.time_;
87
88 hpx::util::format_to(std::cout,
89 " {},{},{}[s],{}\n",
90 name,
91 value.count_,
92 double((value.time_ - zero_time) * 1e-9),
93 value.value_);
94
95 #if defined(HPX_WINDOWS) && HPX_USE_WINDOWS_PERFORMANCE_COUNTERS != 0
96 update_windows_counters(value.value_);
97 #endif
98 }
99
100 // Schedule a wakeup.
101 hpx::this_thread::suspend(pause);
102 }
103
104 return hpx::disconnect();
105 }
106
107 ///////////////////////////////////////////////////////////////////////////////
hpx_main(boost::program_options::variables_map & vm)108 int hpx_main(boost::program_options::variables_map& vm)
109 {
110 std::cout << "starting monitor" << std::endl;
111
112 std::string const name = vm["name"].as<std::string>();
113 std::uint64_t const pause = vm["pause"].as<std::uint64_t>();
114 double const runfor = vm["runfor"].as<double>();
115
116 return monitor(runfor, name, pause);
117 }
118
119 ///////////////////////////////////////////////////////////////////////////////
main(int argc,char * argv[])120 int main(int argc, char* argv[])
121 {
122 // Configure application-specific options.
123 boost::program_options::options_description
124 desc_commandline("Usage: " HPX_APPLICATION_STRING " [options]");
125
126 using boost::program_options::value;
127 desc_commandline.add_options()
128 ( "name", value<std::string>()->default_value(
129 "/threadqueue{locality#0/total}/length")
130 , "symbolic name of the performance counter")
131
132 ( "pause", value<std::uint64_t>()->default_value(500)
133 , "milliseconds between each performance counter query")
134
135 ( "runfor", value<double>()->default_value(-1)
136 , "time to wait before this application exits ([s], default: run forever)")
137 ;
138
139 #if defined(HPX_WINDOWS) && HPX_USE_WINDOWS_PERFORMANCE_COUNTERS != 0
140 hpx::register_startup_function(&install_windows_counters);
141 #endif
142
143 // Initialize and run HPX, enforce connect mode as we connect to an existing
144 // application.
145 std::vector<std::string> const cfg = {
146 "hpx.run_hpx_main!=1"
147 };
148
149 hpx::util::function_nonser<void()> const empty;
150 return hpx::init(desc_commandline, argc, argv, cfg, empty,
151 empty, hpx::runtime_mode_connect);
152 }
153
154