|
1 | 1 | //! The `poh_service` module implements a service that records the passing of
|
2 | 2 | //! "ticks", a measure of time in the PoH stream
|
| 3 | +
|
| 4 | +use std::time::Duration; |
3 | 5 | use {
|
4 | 6 | crate::{
|
5 | 7 | mpsc::{self, Consumer},
|
@@ -236,6 +238,19 @@ impl PohService {
|
236 | 238 | poh: &Arc<Mutex<Poh>>,
|
237 | 239 | target_ns_per_tick: u64,
|
238 | 240 | ) -> bool {
|
| 241 | + // If the difference between min tick height and capacity is small then shutoff. |
| 242 | + // remaining_tick_time, ticks_per_slot, compute_leader_slot_tick_heights |
| 243 | + // tick_height, Bank::max_tick_height |
| 244 | + let tick_height = poh_recorder.read().unwrap().tick_height(); |
| 245 | + let max_tick_height = poh_recorder.read().unwrap().bank().unwrap().max_tick_height(); |
| 246 | + let remaining_slots = max_tick_height - tick_height; |
| 247 | + let min_gap = std::cmp::max(max_tick_height - record_receiver.ring_buffer.capacity(), 64); |
| 248 | + if remaining_slots < min_gap { |
| 249 | + record_receiver.shut_off_producers(); |
| 250 | + if remaining_slots == 0 { |
| 251 | + record_receiver.enable_producers(); // TODO: Do we need to reset the queue? |
| 252 | + } |
| 253 | + } |
239 | 254 | match next_record.take() {
|
240 | 255 | Some(mut record) => {
|
241 | 256 | // received message to record
|
@@ -281,28 +296,35 @@ impl PohService {
|
281 | 296 | // nothing else can be done. tick required.
|
282 | 297 | return true;
|
283 | 298 | }
|
| 299 | + |
284 | 300 | // check to see if a record request has been sent
|
285 | 301 | if let Some(record) = record_receiver.pop() {
|
286 | 302 | // remember the record we just received as the next record to occur
|
287 | 303 | *next_record = Some(record);
|
288 | 304 | break;
|
289 | 305 | }
|
290 | 306 | // check to see if we need to wait to catch up to ideal
|
291 |
| - let wait_start = Instant::now(); |
| 307 | + let mut wait_start = Instant::now(); |
| 308 | + |
292 | 309 | if ideal_time <= wait_start {
|
293 | 310 | // no, keep hashing. We still hold the lock.
|
294 | 311 | continue;
|
295 | 312 | }
|
296 | 313 |
|
297 | 314 | // busy wait, polling for new records and after dropping poh lock (reset can occur, for example)
|
298 | 315 | drop(poh_l);
|
299 |
| - while ideal_time > Instant::now() { |
| 316 | + let d = Duration::from_nanos(target_ns_per_tick*64); |
| 317 | + while ideal_time > wait_start { |
| 318 | + if ideal_time.checked_duration_since(wait_start).unwrap().ge(&d) { |
| 319 | + record_receiver.shut_off_producers() |
| 320 | + } |
300 | 321 | // check to see if a record request has been sent
|
301 | 322 | if let Some(record) = record_receiver.pop() {
|
302 | 323 | // remember the record we just received as the next record to occur
|
303 | 324 | *next_record = Some(record);
|
304 | 325 | break;
|
305 | 326 | }
|
| 327 | + wait_start = Instant::now(); |
306 | 328 | }
|
307 | 329 | timing.total_sleep_us += wait_start.elapsed().as_micros() as u64;
|
308 | 330 | break;
|
|
0 commit comments