$darkmode
simulation_progress.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Robert Bosch GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * SPDX-License-Identifier: Apache-2.0
17  */
22 #pragma once
23 
24 #include <string>
25 #include <chrono>
26 
27 #include <cloe/core.hpp>
28 
29 #include "utility/progress.hpp" // for Progress
30 
31 namespace engine {
32 
38  using TimePoint = std::chrono::steady_clock::time_point;
39 
40  public:
41  std::string stage{""};
42  std::string message{"initializing engine"};
43 
44  Progress initialization;
45  size_t initialization_n;
46  size_t initialization_k;
47 
48  Progress execution;
49  cloe::Duration execution_eta{0};
50 
51  // Reporting:
52  double report_granularity_p{0.1};
53  cloe::Duration report_granularity_d{10'000'000'000};
54  double execution_report_p;
55  TimePoint execution_report_t;
56 
57  public:
58  void init_begin(size_t n) {
59  message = "initializing";
60  initialization.begin();
61  initialization_n = n;
62  initialization_k = 0;
63  }
64 
65  void init(const std::string& what) {
66  stage = what;
67  message = "initializing " + what;
68  initialization_k++;
69  double p = static_cast<double>(initialization_k) / static_cast<double>(initialization_n);
70  initialization.update(p);
71  }
72 
73  void init_end() {
74  initialization_k++;
75  assert(initialization_k == initialization_n);
76  initialization.end();
77  stage = "";
78  message = "initialization done";
79  }
80 
81  bool is_init_ended() const { return initialization.is_ended(); }
82 
83  cloe::Duration elapsed() const {
84  if (is_init_ended()) {
85  return initialization.elapsed() + execution.elapsed();
86  } else {
87  return initialization.elapsed();
88  }
89  }
90 
91  void exec_begin() {
92  stage = "simulation";
93  message = "executing simulation";
94  execution_report_p = 0;
95  execution_report_t = std::chrono::steady_clock::now();
96  execution.begin();
97  }
98 
99  void exec_update(double p) { execution.update_safe(p); }
100 
101  void exec_update(cloe::Duration now) {
102  if (execution_eta != cloe::Duration(0)) {
103  double now_d = static_cast<double>(now.count());
104  double eta_d = static_cast<double>(execution_eta.count());
105  exec_update(now_d / eta_d);
106  }
107  }
108 
109  void exec_end() {
110  stage = "";
111  message = "simulation done";
112  execution.end();
113  }
114 
115  bool is_exec_ended() const { return execution.is_ended(); }
116 
122  bool exec_report() {
123  // We should not report 100% more than once.
124  if (execution_report_p == 1.0) {
125  return false;
126  }
127 
128  // If there is no execution ETA, also don't report.
129  if (execution_eta == cloe::Duration(0)) {
130  return false;
131  }
132 
133  // Certain minimum percentage has passed.
134  auto now = std::chrono::steady_clock::now();
135  if (execution.is_ended()) {
136  // We should report 100% at least once.
137  execution_report_p = 1.0;
138  execution_report_t = now;
139  return true;
140  } else if (execution.percent() - execution_report_p > report_granularity_p) {
141  // We should report at least every report_granularity_p (percent).
142  execution_report_p = execution.percent();
143  execution_report_t = now;
144  return true;
145  } else if (cast_duration(now - execution_report_t) > report_granularity_d) {
146  // We should report at least every report_granularity_d (duration).
147  execution_report_p = execution.percent();
148  execution_report_t = now;
149  return true;
150  } else {
151  return false;
152  }
153  }
154 
155  friend void to_json(cloe::Json& j, const SimulationProgress& p) {
156  j = cloe::Json{
157  {"message", p.message},
158  {"initialization", p.initialization},
159  };
160  if (p.execution_eta > cloe::Duration(0)) {
161  j["execution"] = p.execution;
162  } else {
163  j["execution"] = nullptr;
164  }
165  }
166 };
167 
168 } // namespace engine
Definition: progress.hpp:35
void update_safe(double p)
Definition: progress.hpp:94
double percent() const
Definition: progress.hpp:106
Duration elapsed() const
Definition: progress.hpp:116
void update(double p)
Definition: progress.hpp:73
void end()
Definition: progress.hpp:59
bool is_ended() const
Definition: progress.hpp:68
void begin()
Definition: progress.hpp:50
Definition: simulation_progress.hpp:37
bool exec_report()
Definition: simulation_progress.hpp:122
std::chrono::nanoseconds Duration
Definition: cloe_fwd.hpp:36