Given the average time between output events (`output_time`), the average time between input events (`input_time`) and the buffer size, the method computes the expected time an input event will have to wait. The wait time is approximated as the product of the probability the buffer will be empty and the time it takes to produce an element into the buffer. The formula used for computing the proba
| 46 | // Collects derivatives of `ComputeWaitTime` w.r.t `output_time`, `input_time' |
| 47 | // and `buffer_size` if the corresponding pointers are not `nullptr`. |
| 48 | double ComputeWaitTime(double output_time, double input_time, |
| 49 | double buffer_size, double* output_time_derivative, |
| 50 | double* input_time_derivative, |
| 51 | double* buffer_size_derivative) { |
| 52 | // Case 0: either the producer or the consumer are infinitely fast. Wait time |
| 53 | // is the time to produce an output. |
| 54 | if (output_time == 0 || input_time == 0) { |
| 55 | if (output_time_derivative) { |
| 56 | *output_time_derivative = 1.0L; |
| 57 | } |
| 58 | if (input_time_derivative) { |
| 59 | *input_time_derivative = 0.0L; |
| 60 | } |
| 61 | if (buffer_size_derivative) { |
| 62 | *buffer_size_derivative = 0.0L; |
| 63 | } |
| 64 | return output_time; |
| 65 | } |
| 66 | // Case 1: the consumer is slower than the producer. Wait time is 0 since the |
| 67 | // buffer will be full in the long run. |
| 68 | if (input_time > output_time) { |
| 69 | if (output_time_derivative) { |
| 70 | *output_time_derivative = 0.0L; |
| 71 | } |
| 72 | if (input_time_derivative) { |
| 73 | *input_time_derivative = 0.0L; |
| 74 | } |
| 75 | if (buffer_size_derivative) { |
| 76 | *buffer_size_derivative = 0.0L; |
| 77 | } |
| 78 | return 0; |
| 79 | } |
| 80 | // Case 2: the consumer and the producer are equally fast. Expected wait time |
| 81 | // decreases linearly with the size of the buffer. |
| 82 | if (input_time == output_time) { |
| 83 | const double p_buffer_empty = 1.0L / (buffer_size + 1.0L); |
| 84 | if (output_time_derivative) { |
| 85 | *output_time_derivative = p_buffer_empty; |
| 86 | } |
| 87 | if (input_time_derivative) { |
| 88 | *input_time_derivative = 0.0L; |
| 89 | } |
| 90 | if (buffer_size_derivative) { |
| 91 | const double p_buffer_empty_der = -1.0L / Square(buffer_size + 1.0L); |
| 92 | *buffer_size_derivative = p_buffer_empty_der * output_time; |
| 93 | } |
| 94 | return p_buffer_empty * output_time; |
| 95 | } |
| 96 | // Case 3: the producer is slower than the consumer and neither is infinitely |
| 97 | // fast. |
| 98 | const double alpha = 1.0L / input_time; |
| 99 | const double beta = 1.0L / output_time; |
| 100 | const double ratio_pow = std::pow((beta / alpha), (buffer_size + 1.0L)); |
| 101 | const double p_buffer_empty = (1.0L - beta / alpha) / (1.0L - ratio_pow); |
| 102 | if (output_time_derivative) { |
| 103 | *output_time_derivative = |
| 104 | (1.0L - ratio_pow - |
| 105 | (output_time - input_time) * (buffer_size + 1.0L) * ratio_pow / |
no test coverage detected