diff options
author | Christian Grothoff <christian@grothoff.org> | 2010-10-20 21:53:29 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2010-10-20 21:53:29 +0000 |
commit | fa4128cdbd9857b3446c1fe337c0796eaba76f18 (patch) | |
tree | c668846a2001418254f613077e34923a6b50f53f /src/util/load.c | |
parent | a38a2fd6598a4b774a04818a521fb70c6566c387 (diff) | |
download | gnunet-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.c | 126 |
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 | ||
83 | static void | ||
84 | internal_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 | */ |
78 | struct GNUNET_LOAD_Value * | 117 | struct GNUNET_LOAD_Value * |
79 | GNUNET_LOAD_value_init () | 118 | GNUNET_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 | */ | ||
135 | static void | ||
136 | calculate_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 | */ |
94 | double | 178 | double |
95 | GNUNET_LOAD_get_load (const struct GNUNET_LOAD_Value *load) | 179 | GNUNET_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 | */ |
107 | double | 193 | double |
108 | GNUNET_LOAD_get_average (const struct GNUNET_LOAD_Value *load) | 194 | GNUNET_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 */ |