1 #ifndef MPQC_PROFILE_HPP
2 #define MPQC_PROFILE_HPP
6 #include "boost/date_time/posix_time/posix_time_types.hpp"
13 #include <boost/thread/thread.hpp>
14 #include <boost/thread/mutex.hpp>
15 #include <boost/preprocessor/cat.hpp>
16 #include <boost/preprocessor/stringize.hpp>
17 #include <boost/typeof/typeof.hpp>
51 #define MPQC_PROFILE__(tag) BOOST_PP_CAT(boost_profile__, tag)
53 #ifdef MPQC_PROFILE_ENABLE
54 #define MPQC_PROFILE_FUNCTION(...) \
55 mpqc::profiler::event MPQC_PROFILE__(__LINE__) \
56 (mpqc::global_profiler() \
57 [mpqc::detail::profiler_event \
58 (__PRETTY_FUNCTION__)(__VA_ARGS__)])
60 #define MPQC_PROFILE_TYPE(T, ...) \
61 mpqc::profiler::event MPQC_PROFILE__(__LINE__) \
62 (mpqc::global_profiler() \
63 [mpqc::detail::profiler_event \
64 (typeid(T).name())(__VA_ARGS__)])
66 #define MPQC_PROFILE(...) \
67 mpqc::profiler::event MPQC_PROFILE__(__LINE__) \
68 (mpqc::global_profiler() \
69 [mpqc::detail::profiler_event(__VA_ARGS__)])
71 #define MPQC_PROFILE_LINE \
72 mpqc::profiler::event MPQC_PROFILE__(__LINE__) \
73 (mpqc::global_profiler() \
74 [mpqc::detail::profiler_event(std::string(__FILE__) + ":" + \
75 (BOOST_PP_STRINGIZE(__LINE__)))])
77 #define MPQC_PROFILE_REGISTER_THREAD \
78 mpqc::global_profiler().register_thread()
81 #define MPQC_PROFILE_FUNCTION(...)
82 #define MPQC_PROFILE_TYPE(T, ...)
83 #define MPQC_PROFILE_LINE
84 #define MPQC_PROFILE(...)
85 #define MPQC_PROFILE_REGISTER_THREAD
88 #define MPQC_PROFILE_DUMP(stream) \
89 mpqc::global_profiler().dump((stream))
91 #define MPQC_PROFILE_RESET \
92 mpqc::global_profiler().clear()
97 struct profiler_event {
98 profiler_event(
const std::string &key) : data_(key) {}
99 operator const std::string&()
const {
return data_; }
100 profiler_event& operator()(
const std::string &key) {
101 data_ += (
":" + key);
104 profiler_event& operator()() {
return *
this; }
112 typedef std::string event_key;
115 event_data(): size_(0), value_(0) {}
116 event_data(
const event_data &e)
117 : size_(e.size_), value_(e.value_) {}
118 event_data& operator+=(
double t) {
123 event_data& operator++() {
return (*
this += 1); }
125 O& to_stream(O &ostream)
const {
126 ostream << value_ <<
"/" << size_;
135 event(event_data *data)
137 start_(microsec_clock::universal_time()) {}
139 boost::posix_time::time_duration t =
140 (microsec_clock::universal_time() - start_);
143 *data_ += t.total_microseconds()/1.0e6;
147 typedef boost::posix_time::microsec_clock microsec_clock;
149 boost::posix_time::ptime start_;
153 void register_thread() {
154 boost::lock_guard<boost::mutex> lock(mutex_);
159 event_data* operator[](
const event_key &key) {
161 std::string thread = this->thread();
162 boost::lock_guard<boost::mutex> lock(mutex_);
163 if (events_.find(thread) == events_.end())
return NULL;
165 return &events_[thread][key];
169 boost::lock_guard<boost::mutex> lock(mutex_);
170 BOOST_AUTO(it, events_.begin());
171 while (it != events_.end()) {
172 it++->second.clear();
177 S& to_stream(S &ostream)
const {
178 boost::lock_guard<boost::mutex> lock(mutex_);
179 typedef std::map<event_key, event_data> events_t;
180 typename std::map<std::string, events_t>::const_iterator
183 while (e != events_.end()) {
184 ostream <<
"Thread " << e->first <<
":" << std::endl;
185 typename events_t::const_iterator it = e->second.begin();
186 while (it != e->second.end()) {
187 ostream <<
" " << it->first <<
": ";
188 it->second.to_stream(ostream);
189 ostream << std::endl;
198 void dump(S &stream) {
199 this->to_stream(stream);
204 mutable boost::mutex mutex_;
206 std::string, std::map<event_key, event_data>
209 static std::string thread() {
210 std::stringstream ss;
211 ss << boost::this_thread::get_id();
220 inline std::ostream&
operator<<(std::ostream &ostream,
const profiler<T> &p) {
221 return p.to_stream(ostream);
230 typedef detail::profiler<void> profiler;
231 inline profiler& global_profiler() {
240 #endif // MPQC_PROFILE_HPP