NCBI C++ ToolKit
ncbi_misc.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_misc.cpp 82541 2018-06-11 17:56:27Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Anton Lavrentiev
27  *
28  * File Description:
29  * Miscellaneous C++ connect stuff
30  *
31  */
32 
33 #include <ncbi_pch.hpp>
34 #include <corelib/ncbidbg.hpp>
35 #include <connect/ncbi_misc.hpp>
36 
37 //#define DEBUG_RATE_MONITOR 1
38 
39 #ifdef DEBUG_RATE_MONITOR
40 # include <iterator> // distance()
41 #endif //DEBUG_RATE_MONITOR
42 
43 
45 
46 
47 #ifdef DEBUG_RATE_MONITOR
48 static void x_PrintList(const list<CRateMonitor::TMark>& data)
49 {
51  list<CRateMonitor::TMark>::const_iterator it = data.begin();
52  cout << data.size() << ':' << endl;
53  for (size_t n = 0; n < data.size(); n++) {
55  cout << n << ":\t"
56  "p = " << next.first << ",\t"
57  "t = " << next.second;
58  if (n) {
59  cout << ",\t"
60  "dp = " << prev.first - next.first << ",\t"
61  "dt = " << prev.second - next.second << endl;
62  } else
63  cout << endl;
64  prev = next;
65  ++it;
66  }
67 }
68 #endif //DEBUG_RATE_MONITOR
69 
70 
71 void CRateMonitor::Mark(Uint8 pos, double time)
72 {
73  if (!m_Data.empty()) {
74  if (m_Data.front().first > pos ||
75  m_Data.front().second > time) {
76  return; // invalid input silently ignored
77  }
78  while (m_Data.front().second > m_Data.back().second + kMaxSpan) {
79  m_Data.pop_back();
80  }
81  if (m_Data.size() > 1) {
82  list<TMark>::const_iterator it;
83  if (m_Data.front().first == pos || m_Data.front().second == time
84  || time - (++(it = m_Data.begin()))->second < kSpan
85  || m_Data.front().second - it->second < kSpan) {
86  // update only
87  m_Data.front().first = pos;
88  m_Data.front().second = time;
89 #ifdef DEBUG_RATE_MONITOR
90  cout << "UPDATED" << endl;
91  x_PrintList(m_Data);
92 #endif //DEBUG_RATE_MONITOR
93  m_Rate = 0.0;
94  return;
95  }
96  }
97  }
98  // new mark
99  m_Data.push_front(make_pair(pos, time));
100 #ifdef DEBUG_RATE_MONITOR
101  cout << "ADDED" << endl;
102  x_PrintList(m_Data);
103 #endif //DEBUG_RATE_MONITOR
104  m_Rate = 0.0;
105 }
106 
107 
108 double CRateMonitor::GetRate(void) const
109 {
110  if (m_Rate > 0.0)
111  return m_Rate;
112  size_t n = m_Data.size();
113  if (n < 2)
114  return GetPace();
115 
116  list<TMark> gaps;
117 
118  if (n > 2) {
119  TMark prev = m_Data.front();
120  list<TMark>::const_iterator it = m_Data.begin();
121  _ASSERT(prev.first - m_Data.back().first > kSpan);
122  for (++it; it != m_Data.end(); ++it) {
123  TMark next = *it;
124  double dt = prev.second - next.second;
125  if (dt < kSpan) {
126 #ifdef DEBUG_RATE_MONITOR
127  cout << "dt = " << dt << ",\td =" << (kSpan - dt)
128  << ",\tn = " << distance(m_Data.begin(), it) << endl;
129 #endif //DEBUG_RATE_MONITOR
130  _DEBUG_ARG(list<TMark>::const_iterator beg = m_Data.begin());
131  _ASSERT(it == ++beg);
132  continue;
133  }
134  gaps.push_back(make_pair(prev.first - next.first, dt));
135  prev = next;
136  }
137  } else {
138  double dt = m_Data.front().second - m_Data.back().second;
139  if (dt < kSpan)
140  return GetPace();
141  gaps.push_back(make_pair(m_Data.front().first -
142  m_Data.back ().first, dt));
143  }
144 
145  _ASSERT(!gaps.empty() && !m_Rate);
146 
147  double weight = 1.0;
148  for (;;) {
149  double rate = double(gaps.front().first) / gaps.front().second;
150  gaps.pop_front();
151  if (gaps.empty()) {
152  m_Rate += rate * weight;
153  break;
154  }
155  double w = weight * kWeight;
156  m_Rate += rate * w;
157  weight -= w;
158  }
159  return m_Rate;
160 }
161 
162 
163 double CRateMonitor::GetETA(void) const
164 {
165  if (!m_Size)
166  return 0.0;
167  Uint8 pos = GetPos();
168  if (pos >= m_Size)
169  return 0.0;
170  double rate = GetRate();
171  if (!rate)
172  return -1.0;
173  double eta = double(m_Size - pos) / rate;
174  if (eta < kMinSpan)
175  eta = 0.0;
176  return eta;
177 }
178 
179 
181 {
182  if (!m_Size)
183  return 0.0;
184  Uint8 pos = GetPos();
185  if (!pos)
186  return -1.0;
187  if (pos >= m_Size)
188  return 0.0;
189  double time = m_Data.front().second;
190  // NB: Essentially, there is the same formula as in GetETA(),
191  // if to notice that rate = pos / time in this case.
192  time = time * double(m_Size) / double(pos) - time;
193  if (time < kMinSpan)
194  time = 0.0;
195  return time;
196 }
197 
198 
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:56
char data[12]
Definition: iconv.c:80
#define _DEBUG_ARG(arg)
Definition: ncbidbg.hpp:134
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
double GetETA(void) const
How long it will take to complete, at the current rate.
Definition: ncbi_misc.cpp:163
const double kMinSpan
Definition: ncbi_misc.hpp:122
const double kWeight
Definition: ncbi_misc.hpp:124
const double kSpan
Definition: ncbi_misc.hpp:125
const double kMaxSpan
Definition: ncbi_misc.hpp:123
pair< Uint8, double > TMark
Definition: ncbi_misc.hpp:58
Uint8 GetPos(void) const
Get current progress position (position 0 when job starts)
Definition: ncbi_misc.hpp:141
Uint8 m_Size
Total size of job to be performed.
Definition: ncbi_misc.hpp:129
void Mark(Uint8 pos, double time)
Submit a mark of the job progress.
Definition: ncbi_misc.cpp:71
double GetTimeRemaining(void) const
How long it will take to complete, at the average pace.
Definition: ncbi_misc.cpp:180
list< TMark > m_Data
Measurements as submitted by Mark()
Definition: ncbi_misc.hpp:128
double GetRate(void) const
How fast the recent rate has been, in positions per time unit, using the weighted formula.
Definition: ncbi_misc.cpp:108
double GetPace(void) const
How fast the average pace has been so far, in positions per time unit.
Definition: ncbi_misc.hpp:153
double m_Rate
Cached rate from last calculation.
Definition: ncbi_misc.hpp:127
n font weight
yy_size_t n
NCBI C++ auxiliary debug macros.
#define _ASSERT
Modified on Wed Sep 04 15:01:50 2024 by modify_doxy.py rev. 669887