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