From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 44B636EC5A; Mon, 15 Feb 2021 14:18:03 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 44B636EC5A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1613387883; bh=tUfSyZYW4oUJV1dpmFmG3e1S3sbbwaT5Ge+Dq4Bve3o=; h=Date:To:Cc:References:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=V1fAeqo+BpSp+CkSxO2eAw8RiO8WhdIE7yAP5wJm4hPVC7+8AigQwj6b9ufPM0X9Q Qn/3ieL6t4Jjke2Zi/un0VwtfSl2bDxrjTbvLFu3ESE7isGxCXcIUASJ22zNayn1oZ 1wVOZr/Z2gGhFa/TH+aBJMawlU2LWjU7DWqNEU1o= Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 5D28B6EC5A for ; Mon, 15 Feb 2021 14:18:02 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 5D28B6EC5A Received: by mail-lj1-f171.google.com with SMTP id g11so7243528ljj.7 for ; Mon, 15 Feb 2021 03:18:02 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=1fR0PnztVpPWLtn2M9S6YWssPBe8bmtEhbxbMwv5nzY=; b=cZZMStlQiCncY33qmVzIGd0SReBFiAWGygcKYcGWdyuIy/sdNkeNnVjLSWGwOLP3Bm Z6g/oDI8PgSU5jJGFjClOnwzkPdi4uD6AvYyNUzc/E7HT80YX1ZwkkixTxZrpp9fgjFv w5XxS9tkOT5aAp8IzVa0vlpNwbo8X+QzBIfZATWmyzfU7y/kHdhfyL7W65xvHN58dmV0 rvKgmhsWoMK7WVXTM62+N+XDwus1jBisS75ysqQCZtZ4il/tnyi3s8ar+pFdlf+rihbm KF7mIIt5gm+lch8BBNhJot2jb4sxMGwc1butlXipD+DWWXJhjpK/YjQzN2/QPrAOF7R6 hjpA== X-Gm-Message-State: AOAM5311Vr21HEnByqegTaZbUVGsC5UztXn8EqfzkfUacG4mq3s6wBaO g4RMmhVi3cTKJtxq+Jb05Zc/yJ4oet0= X-Google-Smtp-Source: ABdhPJwO3HaBSC5/e3KMMt/QTfWDeQPI8zl2v6VYgWx2E03puSgrJeTomZix9aiwPpgAtigMnRqomg== X-Received: by 2002:a2e:89cb:: with SMTP id c11mr836223ljk.267.1613387881181; Mon, 15 Feb 2021 03:18:01 -0800 (PST) Received: from grain.localdomain ([5.18.171.94]) by smtp.gmail.com with ESMTPSA id k5sm1598168ljh.130.2021.02.15.03.17.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 15 Feb 2021 03:18:00 -0800 (PST) Received: by grain.localdomain (Postfix, from userid 1000) id 6A2FF560097; Mon, 15 Feb 2021 14:17:59 +0300 (MSK) Date: Mon, 15 Feb 2021 14:17:59 +0300 To: Serge Petrenko Cc: v.shpilevoy@tarantool.org, tarantool-patches@dev.tarantool.org Message-ID: References: <20210211121750.46298-1-sergepetrenko@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210211121750.46298-1-sergepetrenko@tarantool.org> User-Agent: Mutt/2.0.5 (2021-01-21) Subject: Re: [Tarantool-patches] [PATCH v2] wal: introduce limits on simultaneous writes X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Cyrill Gorcunov via Tarantool-patches Reply-To: Cyrill Gorcunov Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" On Thu, Feb 11, 2021 at 03:17:50PM +0300, Serge Petrenko wrote: > diff --git a/src/box/applier.cc b/src/box/applier.cc > index 553db76fc..06aaa0a79 100644 > --- a/src/box/applier.cc > +++ b/src/box/applier.cc > @@ -967,6 +967,15 @@ applier_apply_tx(struct applier *applier, struct stailq *rows) > goto success; > } > > + /* > + * Do not spam WAL with excess write requests, let it process what's > + * piled up first. > + * This is done before opening the transaction to avoid problems with > + * yielding inside it. > + */ > + if (journal_queue_is_full(current_journal)) > + journal_wait_queue(); > + Serge, just a few comments, feel free to ignore. Maybe it would be better to pass current_journal to journal_wait_queue, otherwise it looks somehow inconsistent, no? if (journal_queue_is_full(current_journal)) journal_wait_queue(current_journal); Actually I would name journal queue engine as plain journalq, this would look like if (journalq_is_full(current_journal)) journalq_wait(current_journal); But it is very humble pov, lets stick with long `journal_queue`. ... > +/** Wake the journal queue up. */ > +static inline void > +journal_queue_wakeup(struct journal *j, bool force_ready) > +{ > + assert(j == current_journal); Seems this assert is not needed. The overall idea of passing journal as an argument is quite the reverse, ie to work with any journal. This is not a blocker, could be cleaned up on top or simply ignored. > + assert(!rlist_empty(&j->waiters)); > + if (j->queue_is_woken) > + return; > + j->queue_is_woken = true; > + journal_queue_wakeup_next(&j->waiters, force_ready); > +} > + > +/** > + * Check whether any of the queue size limits is reached. > + * If the queue is full, we must wait for some of the entries to be written > + * before proceeding with a new asynchronous write request. > + */ > +static inline bool > +journal_queue_is_full(struct journal *j) > +{ > + assert(j == current_journal); same, no need for assert() > + return (j->queue_max_size != 0 && j->queue_size >= j->queue_max_size) || > + (j->queue_max_len != 0 && j->queue_len >= j->queue_max_len); > +} > + > +/** > + * Check whether anyone is waiting for the journal queue to empty. If there are > + * other waiters we must go after them to preserve write order. > + */ > +static inline bool > +journal_queue_has_waiters(struct journal *j) > +{ > + assert(j == current_journal); same, no need for assert() > + return !rlist_empty(&j->waiters); > +} > + > +/** Yield until there's some space in the journal queue. */ > +void > +journal_wait_queue(void); > + > /** > * Complete asynchronous write. > */ > @@ -131,15 +199,15 @@ static inline void > journal_async_complete(struct journal_entry *entry) > { > assert(entry->write_async_cb != NULL); > + current_journal->queue_len--; > + current_journal->queue_size -= entry->approx_len; Myabe worth to make queue ops closed into some helper? Because length and size can't be updated without a tangle. IOW, something like static inline void journal_queue_attr_dec(struct journal *j, struct journal_entry *entry) { j->queue_len--; j->queue_size -= entry->approx_len; } static inline void journal_queue_attr_inc(struct journal *j, struct journal_entry *entry) { j->queue_len++; j->queue_size += entry->approx_len; } Again, this is my pov, **free to ignore**. attr here stands for attributes because queue_len and queue_size are not the queue itself but attributes which controls when we need to wait data to be flushed. > + assert(current_journal->queue_len >= 0); > + assert(current_journal->queue_size >= 0); > + if (journal_queue_has_waiters(current_journal)) > + journal_queue_wakeup(current_journal, false); > entry->write_async_cb(entry); > }