aboutsummaryrefslogtreecommitdiff
path: root/src/util/load.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-10-20 21:53:29 +0000
committerChristian Grothoff <christian@grothoff.org>2010-10-20 21:53:29 +0000
commitfa4128cdbd9857b3446c1fe337c0796eaba76f18 (patch)
treec668846a2001418254f613077e34923a6b50f53f /src/util/load.c
parenta38a2fd6598a4b774a04818a521fb70c6566c387 (diff)
downloadgnunet-fa4128cdbd9857b3446c1fe337c0796eaba76f18.tar.gz
gnunet-fa4128cdbd9857b3446c1fe337c0796eaba76f18.zip
improved load API to hopefully fix fs load mgmt troubles
Diffstat (limited to 'src/util/load.c')
-rw-r--r--src/util/load.c126
1 files changed, 94 insertions, 32 deletions
diff --git a/src/util/load.c b/src/util/load.c
index 7eff40919..fd8a5afab 100644
--- a/src/util/load.c
+++ b/src/util/load.c
@@ -35,6 +35,16 @@ struct GNUNET_LOAD_Value
35{ 35{
36 36
37 /** 37 /**
38 * How fast should the load decline if no values are added?
39 */
40 struct GNUNET_TIME_Relative autodecline;
41
42 /**
43 * Last time this load value was updated by an event.
44 */
45 struct GNUNET_TIME_Absolute last_update;
46
47 /**
38 * Sum of all datastore delays ever observed (in ms). Note that 48 * Sum of all datastore delays ever observed (in ms). Note that
39 * delays above 64k ms are excluded (to avoid overflow within 49 * delays above 64k ms are excluded (to avoid overflow within
40 * first 4 billion requests). 50 * first 4 billion requests).
@@ -70,15 +80,89 @@ struct GNUNET_LOAD_Value
70}; 80};
71 81
72 82
83static void
84internal_update (struct GNUNET_LOAD_Value *load)
85{
86 struct GNUNET_TIME_Relative delta;
87 unsigned int n;
88
89 if (load->autodecline.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
90 return;
91 delta = GNUNET_TIME_absolute_get_duration (load->last_update);
92 if (delta.value < load->autodecline.value)
93 return;
94 n = delta.value / load->autodecline.value;
95 if (n > 16)
96 {
97 load->runavg_delay = 0.0;
98 load->load = 0;
99 return;
100 }
101 while (n > 0)
102 {
103 n--;
104 load->runavg_delay = (load->runavg_delay * 7.0) / 8.0;
105 }
106}
107
108
73/** 109/**
74 * Create a new load value. 110 * Create a new load value.
75 * 111 *
112 * @param autodecline speed at which this value should automatically
113 * decline in the absence of external events; at the given
114 * frequency, 0-load values will be added to the load
76 * @return the new load value 115 * @return the new load value
77 */ 116 */
78struct GNUNET_LOAD_Value * 117struct GNUNET_LOAD_Value *
79GNUNET_LOAD_value_init () 118GNUNET_LOAD_value_init (struct GNUNET_TIME_Relative autodecline)
80{ 119{
81 return GNUNET_malloc (sizeof (struct GNUNET_LOAD_Value)); 120 struct GNUNET_LOAD_Value *ret;
121
122 GNUNET_assert (autodecline.value != 0);
123 ret = GNUNET_malloc (sizeof (struct GNUNET_LOAD_Value));
124 ret->autodecline = autodecline;
125 ret->last_update = GNUNET_TIME_absolute_get ();
126 return ret;
127}
128
129
130/**
131 * Recalculate our load value.
132 *
133 * @param load load to update
134 */
135static void
136calculate_load (struct GNUNET_LOAD_Value *load)
137{
138 double stddev;
139 double avgdel;
140 double sum_val_i;
141 double n;
142 double nm1;
143
144 if (load->cummulative_request_count == 0)
145 return;
146 /* calcuate std dev of latency; we have for n values of "i" that:
147
148 avg = (sum val_i) / n
149 stddev = (sum (val_i - avg)^2) / (n-1)
150 = (sum (val_i^2 - 2 avg val_i + avg^2) / (n-1)
151 = (sum (val_i^2) - 2 avg sum (val_i) + n * avg^2) / (n-1)
152 */
153 sum_val_i = (double) load->cummulative_delay;
154 n = ((double) load->cummulative_request_count);
155 nm1 = n - 1.0;
156 avgdel = sum_val_i / n;
157 stddev = (((double) load->cummulative_squared_delay) - 2.0 * avgdel * sum_val_i + n * avgdel * avgdel) / nm1;
158 if (stddev <= 0)
159 stddev = 0.01; /* must have been rounding error or zero; prevent division by zero */
160 /* now calculate load based on how far out we are from
161 std dev; or if we are below average, simply assume load zero */
162 if (load->runavg_delay < avgdel)
163 load->load = 0.0;
164 else
165 load->load = (load->runavg_delay - avgdel) / stddev;
82} 166}
83 167
84 168
@@ -92,8 +176,10 @@ GNUNET_LOAD_value_init ()
92 * that we could not do proper calculations 176 * that we could not do proper calculations
93 */ 177 */
94double 178double
95GNUNET_LOAD_get_load (const struct GNUNET_LOAD_Value *load) 179GNUNET_LOAD_get_load (struct GNUNET_LOAD_Value *load)
96{ 180{
181 internal_update (load);
182 calculate_load (load);
97 return load->load; 183 return load->load;
98} 184}
99 185
@@ -105,11 +191,12 @@ GNUNET_LOAD_get_load (const struct GNUNET_LOAD_Value *load)
105 * @return zero if update was never called 191 * @return zero if update was never called
106 */ 192 */
107double 193double
108GNUNET_LOAD_get_average (const struct GNUNET_LOAD_Value *load) 194GNUNET_LOAD_get_average (struct GNUNET_LOAD_Value *load)
109{ 195{
110 double n; 196 double n;
111 double sum_val_i; 197 double sum_val_i;
112 198
199 internal_update (load);
113 if (load->cummulative_request_count == 0) 200 if (load->cummulative_request_count == 0)
114 return 0.0; 201 return 0.0;
115 n = ((double) load->cummulative_request_count); 202 n = ((double) load->cummulative_request_count);
@@ -129,12 +216,9 @@ GNUNET_LOAD_update (struct GNUNET_LOAD_Value *load,
129 uint64_t data) 216 uint64_t data)
130{ 217{
131 uint32_t dv; 218 uint32_t dv;
132 double stddev;
133 double avgdel;
134 double sum_val_i;
135 double n;
136 double nm1;
137 219
220 internal_update (load);
221 load->last_update = GNUNET_TIME_absolute_get ();
138 if (data > 64 * 1024) 222 if (data > 64 * 1024)
139 { 223 {
140 /* very large */ 224 /* very large */
@@ -146,30 +230,8 @@ GNUNET_LOAD_update (struct GNUNET_LOAD_Value *load,
146 load->cummulative_squared_delay += dv * dv; 230 load->cummulative_squared_delay += dv * dv;
147 load->cummulative_request_count++; 231 load->cummulative_request_count++;
148 load->runavg_delay = ((load->runavg_delay * 7.0) + dv) / 8.0; 232 load->runavg_delay = ((load->runavg_delay * 7.0) + dv) / 8.0;
149 if (load->cummulative_request_count > 1)
150 {
151 /* calcuate std dev of latency; we have for n values of "i" that:
152
153 avg = (sum val_i) / n
154 stddev = (sum (val_i - avg)^2) / (n-1)
155 = (sum (val_i^2 - 2 avg val_i + avg^2) / (n-1)
156 = (sum (val_i^2) - 2 avg sum (val_i) + n * avg^2) / (n-1)
157 */
158 sum_val_i = (double) load->cummulative_delay;
159 n = ((double) load->cummulative_request_count);
160 nm1 = n - 1.0;
161 avgdel = sum_val_i / n;
162 stddev = (((double) load->cummulative_squared_delay) - 2.0 * avgdel * sum_val_i + n * avgdel * avgdel) / nm1;
163 if (stddev <= 0)
164 stddev = 0.01; /* must have been rounding error or zero; prevent division by zero */
165 /* now calculate load based on how far out we are from
166 std dev; or if we are below average, simply assume load zero */
167 if (load->runavg_delay < avgdel)
168 load->load = 0.0;
169 else
170 load->load = (load->runavg_delay - avgdel) / stddev;
171 }
172} 233}
173 234
174 235
236
175/* end of load.c */ 237/* end of load.c */