Statistics
| Branch: | Revision:

streamers / ratecontrol.c @ 15d2a12c

History | View | Annotate | Download (3.26 KB)

1
/*
2
 *  Copyright (c) 2011 Csaba Kiraly
3
 *
4
 *  This is free software; see gpl-3.0.txt
5
 */
6

    
7
#include <stdint.h>
8
#include <sys/time.h>
9
#include <math.h>
10
#include <string.h>
11

    
12
#include "transaction.h"
13
#include "measures.h"
14
#include "dbg.h"
15

    
16
#define MAX(A,B)    ((A)>(B) ? (A) : (B))
17
#define MIN(A,B)    ((A)<(B) ? (A) : (B))
18

    
19
bool autotune_period = false;
20

    
21
static double offer_accept = 1;
22
static double acc_to_ack = 0;
23

    
24
double offer_accept_smoothing = 0.9;        // %
25
double offer_accept_min = 0.3;        // %
26
double acc_to_ack_max = 0.075;        // sec
27
double period_change_rate_up = 1.0;        // %/sec
28
double period_change_rate_down = 0.1;        // %/sec
29

    
30
extern struct timeval period;
31
#define PERIOD_MIN 1000
32
#define PERIOD_MAX 1000000
33

    
34
int64_t tv2int(struct timeval *tv)
35
{
36
  return tv->tv_sec * 1000000 + tv->tv_usec;
37
}
38

    
39
void int2tv(struct timeval *tv, int64_t t)
40
{
41
  tv->tv_sec = t / 1000000;
42
  tv->tv_usec = t % 1000000;
43
}
44

    
45
static int64_t get_period()
46
{
47
  return tv2int(&period);
48
}
49

    
50
static void set_period(int64_t p)
51
{
52
  int2tv(&period, p);
53
}
54

    
55
static void update_period()
56
{
57
  static struct timeval period_last_updated;
58
  struct timeval t_now;
59
  int64_t dt;
60
  double d_offer_accept;
61
  double d_acc_to_ack;
62
  static int64_t period_initial;
63
  double d_period;
64

    
65
  if (! period_initial) period_initial = get_period();
66

    
67
  gettimeofday(&t_now, NULL);
68

    
69
  dprintf("update_period: offer_accept=%f acc_to_ack=%f period=%lu\n", offer_accept, acc_to_ack, get_period());
70

    
71
  if (timerisset(&period_last_updated)) {
72
    dt = tv2int(&t_now) - tv2int(&period_last_updated);
73
  } else {
74
    dt = tv2int(&period);
75
  }
76
  period_last_updated = t_now;
77

    
78
  d_offer_accept = offer_accept - offer_accept_min;
79
  d_acc_to_ack = (acc_to_ack - acc_to_ack_max) / acc_to_ack_max;
80
  d_period = log(get_period()) - log(period_initial);
81

    
82
  if (d_period < 0) { // we are fast
83
    if (d_offer_accept > 0 && d_acc_to_ack < 0) { // be faster
84
      set_period(MAX(PERIOD_MIN, get_period() / (1.0 + (period_change_rate_down * (1 + fabs(d_period > 0 ? d_period : 0) ) * dt / 1e6))));
85
    } else { //slow down towards normal speed
86
      set_period(MIN(PERIOD_MAX, get_period() * (1.0 + (period_change_rate_up * (1 + fabs(d_period < 0 ? d_period : 0) ) * dt / 1e6))));
87
    }
88
  } else { // we are slow
89
    if (d_acc_to_ack > 0) { // slow down even more
90
      set_period(MIN(PERIOD_MAX, get_period() * (1.0 + (period_change_rate_up * (1 + fabs(d_period < 0 ? d_period : 0) ) * dt / 1e6))));
91
    } else { //recover speed
92
      set_period(MAX(PERIOD_MIN, get_period() / (1.0 + (period_change_rate_down * (1 + fabs(d_period > 0 ? d_period : 0) ) * dt / 1e6))));
93
    }
94
  }
95
}
96

    
97
static void update_offer_accept(bool accepted)
98
{
99
  offer_accept = offer_accept * offer_accept_smoothing + (accepted ? 1 - offer_accept_smoothing : 0);
100
}
101

    
102
static void update_acc_to_ack(double t)
103
{
104
  reg_queue_delay(t);
105
  acc_to_ack = t;
106
  if (autotune_period) {
107
    update_period();
108
  }
109
}
110

    
111

    
112
void rc_reg_accept(uint16_t trans_id, int accepted)
113
{
114
  update_offer_accept(accepted);
115
}
116

    
117
void rc_reg_ack(uint16_t trans_id)
118
{
119
  double t_acc, t_acc_to_ack;
120
  struct timeval t_now;
121

    
122
  t_acc = transaction_remove(trans_id);
123

    
124
  if (t_acc < 0) {
125
    dprintf(" can't find transaction for trans_id %d.\n", trans_id);
126
    return;
127
  }
128

    
129
  gettimeofday(&t_now, NULL);
130
  t_acc_to_ack = t_now.tv_sec + t_now.tv_usec*1e-6 - t_acc;
131

    
132
  update_acc_to_ack(t_acc_to_ack);
133
}