1 #include <ncbi_pch.hpp>
2 #include <corelib/ncbifile.hpp>
3 #include <stdlib.h>
4
5 #include <util/profile/rtprofile.hpp>
6 #include <corelib/ncbi_process.hpp>
7
8 BEGIN_NCBI_SCOPE
9
10 CRtProfiler* CRtProfiler::instance = 0;
11
getInstance()12 CRtProfiler* CRtProfiler::getInstance()
13 {
14 if (instance == 0){
15 instance = new CRtProfiler();
16 }
17 return instance;
18 }
19
20
CRtProfiler(size_t stop_watch_sz)21 CRtProfiler::CRtProfiler ( size_t stop_watch_sz )
22 {
23 if ( stop_watch_sz ) {
24 for( size_t sw_ndx = 0; sw_ndx < stop_watch_sz; ++sw_ndx ){
25 m_sw_vec.push_back( CStopWatch() );
26 }
27 }
28 }
29
Allocate(size_t sw_ndx)30 void CRtProfiler::Allocate( size_t sw_ndx){
31 if( sw_ndx < m_sw_vec.size() ) return; // array is larger enought
32 // ok. user index is larger then current size, enlarge ( ru-tim penalties )
33 for( size_t sw_item_ndx = m_sw_vec.size(); sw_item_ndx < sw_ndx; ++sw_item_ndx ){
34 m_sw_vec.push_back( CStopWatch() );
35 }
36 }
Allocate(std::string sw_name)37 void CRtProfiler::Allocate(std::string sw_name){
38 std::map< std::string,CStopWatch >::iterator it = m_sw_map.find( sw_name );
39 if( it != m_sw_map.end() ) return; // CStopWach already exists wih this name
40 // allocate new CStopWatch instance with this name
41 m_sw_map[ sw_name ] = CStopWatch();
42 }
Start(size_t sw_ndx)43 void CRtProfiler::Start( size_t sw_ndx){
44 if( sw_ndx < m_sw_vec.size() ) Allocate( sw_ndx);
45 m_sw_vec[ sw_ndx ].Start();
46 }
Start(std::string sw_name)47 void CRtProfiler::Start(std::string sw_name){
48 std::map< std::string,CStopWatch >::iterator it = m_sw_map.find( sw_name );
49 if( it == m_sw_map.end() ) Allocate( sw_name);
50 m_sw_map[ sw_name ].Start();
51 }
StartMT(size_t sw_ndx)52 void CRtProfiler::StartMT( size_t sw_ndx){
53 m_sw_vec_mx.Lock();
54 Start(sw_ndx);
55 m_sw_vec_mx.Unlock();
56 }
StartMT(std::string sw_name)57 void CRtProfiler::StartMT(std::string sw_name){
58 m_sw_map_mx.Lock();
59 Start(sw_name);
60 m_sw_map_mx.Unlock();
61 }
Stop(size_t sw_ndx)62 void CRtProfiler::Stop( size_t sw_ndx){
63 if( sw_ndx > m_sw_vec.size() ) return;
64 m_sw_vec[ sw_ndx ].Stop();
65 }
Stop(std::string sw_name)66 void CRtProfiler::Stop(std::string sw_name){
67 std::map< std::string,CStopWatch >::iterator it = m_sw_map.find( sw_name );
68 if( it == m_sw_map.end() ) return;
69 m_sw_map[ sw_name ].Stop();
70 }
StopMT(size_t sw_ndx)71 void CRtProfiler::StopMT(size_t sw_ndx){
72 m_sw_vec_mx.Lock();
73 Stop(sw_ndx);
74 m_sw_vec_mx.Unlock();
75 }
StopMT(std::string sw_name)76 void CRtProfiler::StopMT(std::string sw_name){
77 m_sw_map_mx.Lock();
78 Stop(sw_name);
79 m_sw_map_mx.Unlock();
80 }
AddUserKV(const std::string & key_name,bool bool_val)81 void CRtProfiler::AddUserKV(const std::string &key_name, bool bool_val ){
82 std::string key_val = (bool_val?string("TRUE"):string("FALSE"));
83 AddUserKV( key_name, key_val);
84 }
AddUserKVMT(const std::string & key_name,bool bool_val)85 void CRtProfiler::AddUserKVMT(const std::string &key_name, bool bool_val ){
86 std::string key_val = (bool_val?string("TRUE"):string("FALSE"));
87 m_user_data_mx.Lock();
88 AddUserKV( key_name, key_val);
89 m_user_data_mx.Unlock();
90 }
AddUserKV(const std::string & key_name,int int_val)91 void CRtProfiler::AddUserKV(const std::string &key_name, int int_val ){
92 std::string key_val = NStr::NumericToString( int_val );
93 AddUserKV( key_name, key_val);
94 }
AddUserKVMT(const std::string & key_name,int int_val)95 void CRtProfiler::AddUserKVMT(const std::string &key_name, int int_val ){
96 std::string key_val = NStr::NumericToString( int_val );
97 m_user_data_mx.Lock();
98 AddUserKV( key_name, key_val);
99 m_user_data_mx.Unlock();
100 }
AddUserKVMT(const std::string & key_name,const std::string & key_val)101 void CRtProfiler::AddUserKVMT(const std::string &key_name, const std::string &key_val ){
102 m_user_data_mx.Lock();
103 AddUserKV( key_name, key_val);
104 m_user_data_mx.Unlock();
105 }
AddUserKV(const std::string & key_name,const std::string & key_val)106 void CRtProfiler::AddUserKV(const std::string &key_name, const std::string &key_val ){
107 m_user_data.push_back( std::make_pair( key_name, key_val) );
108 }
AsString(size_t sw_ndx,const CTimeFormat & fmt)109 std::string CRtProfiler::AsString (size_t sw_ndx, const CTimeFormat &fmt) {
110 if( sw_ndx > m_sw_vec.size() ) return string("BAD_INDEX:") + NStr::NumericToString( (int) sw_ndx) ;
111 return m_sw_vec[ sw_ndx ].AsString (fmt);
112 }
113
AsString(std::string sw_name,const CTimeFormat & fmt)114 std::string CRtProfiler::AsString (std::string sw_name, const CTimeFormat &fmt) {
115 std::map< std::string,CStopWatch >::const_iterator it = m_sw_map.find( sw_name );
116 if( it == m_sw_map.end() ) return string("BAD_NAME:") + sw_name;
117 return m_sw_map[ sw_name ].AsString (fmt);
118 }
AsStringMT(size_t sw_ndx,const CTimeFormat & fmt)119 std::string CRtProfiler::AsStringMT (size_t sw_ndx, const CTimeFormat &fmt){
120 string ret_str;
121 m_sw_vec_mx.Lock();
122 ret_str = AsString(sw_ndx,fmt);
123 m_sw_vec_mx.Unlock();
124 return ret_str;
125 }
AsStringMT(std::string sw_name,const CTimeFormat & fmt)126 std::string CRtProfiler::AsStringMT (std::string sw_name, const CTimeFormat &fmt){
127 string ret_str;
128 m_sw_map_mx.Lock();
129 ret_str = AsString(sw_name,fmt);
130 m_sw_map_mx.Unlock();
131 return ret_str;
132 }
133
AddMarkerMT(std::string new_marker)134 void CRtProfiler::AddMarkerMT (std::string new_marker){
135 CTimeFormat ctfmt("Y-M-DTh:m:g");
136 CTime time_now( CTime::eCurrent );
137
138 std::string new_time_str = time_now.AsString( ctfmt );
139
140 m_markers_mx.Lock();
141 m_markers.push_back( std::make_pair ( new_marker, new_time_str ) );
142 m_markers_mx.Unlock();
143 return;
144 }
145 //
146 // environment variable BLASTAPI_PROFILE_LOG:
147 // 1) not set - no report
148 // 2) false - no report
149 // 3) true - do report, report name name: blastapi_profile.csv
150 // 4) any string not 'false' - do report, report name == environment variable
CheckDoReport(std::string & report_name)151 bool CRtProfiler::CheckDoReport( std::string &report_name ) {
152 string profile_log = "blastapi_profile.csv";
153 char *env_ptr = getenv("BLASTAPI_PROFILE_LOG");
154 if( env_ptr == NULL ) return false; // no loging #1
155 if( !NStr::CompareNocase( string(env_ptr),"false") ) return false; // no loging #2
156 report_name = profile_log; // default name
157 if( NStr::CompareNocase( string(env_ptr),"true") ) {
158 profile_log = string( env_ptr ) ; // custom name #4
159 }
160 return true;
161 }
DoReport(const CTimeFormat & fmt)162 bool CRtProfiler::DoReport(const CTimeFormat &fmt) {
163 std::string report_name;
164 if( !CheckDoReport( report_name ) ) return false;
165 std::ofstream log_ofs;
166
167 // REPORT #1 =======================================================================
168 if( !m_user_data.empty() ) {
169 log_ofs.open (report_name.c_str(), std::ofstream::out | std::ofstream::app);
170 if (log_ofs.fail()) {
171 cerr << "Can't log profile data to the \""<< report_name<<"\" errno: "
172 << errno << endl;
173 return false; //
174 }
175 //................................
176 std::map< std::string,CStopWatch >::iterator item_itr;
177 log_ofs <<"PID, "<< CCurrentProcess::GetPid() <<", ";
178 // add user data if any
179 std::list< std::pair< std::string, std::string >>::iterator user_it;
180 for( user_it=m_user_data.begin(); user_it!=m_user_data.end(); user_it++){
181 string key_val = user_it->second;
182 if( key_val.empty() ) key_val = "NOT_SET";
183 log_ofs << user_it->first << " ," << key_val << ", ";
184 }
185
186 for( item_itr=m_sw_map.begin(); item_itr!=m_sw_map.end(); item_itr++) {
187 log_ofs << item_itr->first
188 << ", "
189 << item_itr->second.AsString (fmt)
190 << ", ";
191 }
192 log_ofs << "\n";
193 //................................
194 log_ofs.close();
195 }
196 // REPORT #2 =======================================================================
197 if( !m_markers.empty() ) {
198 string pid_str = NStr::NumericToString( CCurrentProcess::GetPid() );
199 report_name = report_name + string(".") + pid_str;
200 log_ofs.open (report_name.c_str(), std::ofstream::out);
201 if (log_ofs.fail()) {
202 cerr << "Can't log profile data to the \""<< report_name<<"\" errno: "
203 << errno << endl;
204 return false; //
205 }
206 log_ofs << "#PID: "<<pid_str << endl;
207 std::list< std::pair <std::string, std::string> >::iterator it2;
208 for( it2 = m_markers.begin(); it2 != m_markers.end(); it2 ++ ) {
209 log_ofs << it2->first << "," << it2->second << endl;
210 }
211 log_ofs << "\n";
212 log_ofs.close();
213 }
214
215 return true;
216 }
217 /*
218 * string batch_num_str = NStr::NumericToString( batch_ndx );
219 *
220 *
221 *
222 */
223 END_NCBI_SCOPE
224 /* @} */
225
226