[PATCH] Upstream hash: speedup consistent hash init
Wai Keen Woon
waikeen.woon at onapp.com
Wed Feb 18 12:07:36 UTC 2015
# HG changeset patch
# User Wai Keen Woon <waikeen.woon at onapp.com>
# Date 1424259253 -28800
# Wed Feb 18 19:34:13 2015 +0800
# Node ID 34578fd8055e08db2e7bf1e6637b26e92bb1a89b
# Parent 3f568dd68af147b5ba259a27fdc6645f99e87aa7
Upstream hash: speedup consistent hash init
Repeatedly calling ngx_http_upstream_add_chash_point() to create
the points array in sorted order, is O(n^2) to the total weight.
This can cause nginx startup and reconfigure to be substantially
delayed. For example, when total weight is 1000, startup takes 4s.
Replace this with a linear any-order insertion followed by qsort().
Startup time for total weight of 1000 reduces to 40ms.
Note that in the original implementation, if there are points
with duplicate hash, only the first is kept. In this change, all
are included.
diff -r 3f568dd68af1 -r 34578fd8055e
src/http/modules/ngx_http_upstream_hash_module.c
--- a/src/http/modules/ngx_http_upstream_hash_module.c Tue Feb 17
16:27:52 2015 +0300
+++ b/src/http/modules/ngx_http_upstream_hash_module.c Wed Feb 18
19:34:13 2015 +0800
@@ -49,10 +49,10 @@
static ngx_int_t ngx_http_upstream_init_chash(ngx_conf_t *cf,
ngx_http_upstream_srv_conf_t *us);
-static void ngx_http_upstream_add_chash_point(
- ngx_http_upstream_chash_points_t *points, uint32_t hash, ngx_str_t
*server);
static ngx_uint_t ngx_http_upstream_find_chash_point(
ngx_http_upstream_chash_points_t *points, uint32_t hash);
+static int ngx_libc_cdecl
+ ngx_http_upstream_chash_cmp(const void *one, const void *two);
static ngx_int_t ngx_http_upstream_init_chash_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us);
static ngx_int_t
ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc,
@@ -360,12 +360,19 @@
ngx_crc32_update(&hash, (u_char *) &prev_hash,
sizeof(uint32_t));
ngx_crc32_final(hash);
- ngx_http_upstream_add_chash_point(points, hash, &peer->server);
+ points->point[points->number].hash = hash;
+ points->point[points->number].server = server;
+ points->number++;
prev_hash = hash;
}
}
+ ngx_qsort(points->point, points->number,
+ sizeof(ngx_http_upstream_chash_point_t),
+ ngx_http_upstream_chash_cmp);
+
+
hcf = ngx_http_conf_upstream_srv_conf(us,
ngx_http_upstream_hash_module);
hcf->points = points;
@@ -373,31 +380,6 @@
}
-static void
-ngx_http_upstream_add_chash_point(ngx_http_upstream_chash_points_t *points,
- uint32_t hash, ngx_str_t *server)
-{
- size_t size;
- ngx_uint_t i;
- ngx_http_upstream_chash_point_t *point;
-
- i = ngx_http_upstream_find_chash_point(points, hash);
- point = &points->point[i];
-
- if (point->hash == hash) {
- return;
- }
-
- size = (points->number - i) * sizeof(ngx_http_upstream_chash_point_t);
-
- ngx_memmove(point + 1, point, size);
-
- points->number++;
- point->hash = hash;
- point->server = server;
-}
-
-
static ngx_uint_t
ngx_http_upstream_find_chash_point(ngx_http_upstream_chash_points_t
*points,
uint32_t hash)
@@ -430,6 +412,21 @@
}
+static int ngx_libc_cdecl
+ngx_http_upstream_chash_cmp(const void *one, const void *two)
+{
+ if (((ngx_http_upstream_chash_point_t *) one)->hash <
+ ((ngx_http_upstream_chash_point_t *) two)->hash) {
+ return -1;
+ } else if (((ngx_http_upstream_chash_point_t *) one)->hash >
+ ((ngx_http_upstream_chash_point_t *) two)->hash) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
static ngx_int_t
ngx_http_upstream_init_chash_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us)
More information about the nginx-devel
mailing list