From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 621C624546 for ; Wed, 3 Jul 2019 19:27:45 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EWzZ-8d-E5vM for ; Wed, 3 Jul 2019 19:27:45 -0400 (EDT) Received: from smtp36.i.mail.ru (smtp36.i.mail.ru [94.100.177.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 2432C20E3E for ; Wed, 3 Jul 2019 19:27:45 -0400 (EDT) From: Vladislav Shpilevoy Subject: [tarantool-patches] [PATCH 5/5] swim: speed-up empty payloads cluster bootstrap Date: Thu, 4 Jul 2019 01:28:34 +0200 Message-Id: In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-Help: List-Unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-Subscribe: List-Owner: List-post: List-Archive: To: tarantool-patches@freelists.org Cc: kostja@tarantool.org One another place consuming most of the tests start up time is useless dissemination of an empty payload, which can be skipped in fact. Consider a cluster of 300 nodes. Each one of them are interconnected manually, and now a test wants to wait for a stabilization, when there are no events. On such a cluster it happens for ~200 round steps till there are no any single event. This is not about big packets, or log() TTD. There may be a few events, may be more, but when a test wants the cluster to be clean, it needs to wait for all the events being done. This patch abuses the fact, that empty payloads can be compared for free, no any single memcmp. If both new and the old payload are empty, then nothing to disseminate. It could help in a real cluster too, if initially there are no payloads. Needed for #4253 --- src/lib/swim/swim.c | 13 ++++++++++++- test/unit/swim.c | 19 ++++++------------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/lib/swim/swim.c b/src/lib/swim/swim.c index e9f99015c..eda255e6f 100644 --- a/src/lib/swim/swim.c +++ b/src/lib/swim/swim.c @@ -728,9 +728,20 @@ swim_update_member_payload(struct swim *swim, struct swim_member *member, return -1; } memcpy(new_payload, payload, payload_size); - } else { + } else if (member->payload_size > 0) { free(member->payload); new_payload = NULL; + } else { + /* + * A special free-to-check case. Both new and old + * payloads are empty usually at a cluster + * startup. Skip of that useless event frees one + * slot in UDP packets for something more + * meaningful, and speeds up the tests. + */ + assert(member->payload_size == 0 && payload_size == 0); + member->is_payload_up_to_date = true; + return 0; } member->payload = new_payload; member->payload_size = payload_size; diff --git a/test/unit/swim.c b/test/unit/swim.c index 263816c0c..1371e7d26 100644 --- a/test/unit/swim.c +++ b/test/unit/swim.c @@ -866,7 +866,7 @@ swim_cluster_delete_f(va_list ap) static void swim_test_triggers(void) { - swim_start_test(23); + swim_start_test(20); struct swim_cluster *cluster = swim_cluster_new(2); swim_cluster_set_ack_timeout(cluster, 1); struct trigger_ctx tctx, tctx2; @@ -891,16 +891,9 @@ swim_test_triggers(void) "ctx.member is set"); is(tctx.ctx.events, SWIM_EV_NEW, "ctx.events is set"); - swim_run_for(1); - swim_cluster_run_triggers(cluster); - is(tctx.counter, 2, "payload is delivered, trigger caught that"); - is(tctx.ctx.member, swim_cluster_member_view(cluster, 0, 1), - "S1 got S2' payload"); - is(tctx.ctx.events, SWIM_EV_NEW_PAYLOAD, "mask says that"); - swim_cluster_member_set_payload(cluster, 0, "123", 3); swim_cluster_run_triggers(cluster); - is(tctx.counter, 3, "self payload is updated"); + is(tctx.counter, 2, "self payload is updated"); is(tctx.ctx.member, swim_self(s1), "self is set as a member"); is(tctx.ctx.events, SWIM_EV_NEW_PAYLOAD | SWIM_EV_NEW_VERSION, "both version and payload events are presented"); @@ -909,18 +902,18 @@ swim_test_triggers(void) fail_if(swim_cluster_wait_status(cluster, 0, 1, MEMBER_SUSPECTED, 3) != 0); swim_cluster_run_triggers(cluster); - is(tctx.counter, 4, "suspicion fired a trigger"); + is(tctx.counter, 3, "suspicion fired a trigger"); is(tctx.ctx.events, SWIM_EV_NEW_STATUS, "status suspected"); fail_if(swim_cluster_wait_status(cluster, 0, 1, MEMBER_DEAD, 3) != 0); swim_cluster_run_triggers(cluster); - is(tctx.counter, 5, "death fired a trigger"); + is(tctx.counter, 4, "death fired a trigger"); is(tctx.ctx.events, SWIM_EV_NEW_STATUS, "status dead"); fail_if(swim_cluster_wait_status(cluster, 0, 1, swim_member_status_MAX, 2) != 0); swim_cluster_run_triggers(cluster); - is(tctx.counter, 6, "drop fired a trigger"); + is(tctx.counter, 5, "drop fired a trigger"); is(tctx.ctx.events, SWIM_EV_DROP, "status dropped"); is(swim_cluster_member_view(cluster, 0, 1), NULL, "dropped member is not presented in the member table"); @@ -940,7 +933,7 @@ swim_test_triggers(void) swim_cluster_add_link(cluster, 0, 1); swim_cluster_run_triggers(cluster); is(tctx2.counter, 1, "yielding trigger is fired"); - is(tctx.counter, 6, "non-yielding still is not"); + is(tctx.counter, 5, "non-yielding still is not"); struct fiber *async_delete_fiber = fiber_new("async delete", swim_cluster_delete_f); -- 2.20.1 (Apple Git-117)