Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pcXt5-0007a1-F4 for pgsql-hackers@arkaria.postgresql.org; Wed, 15 Mar 2023 20:38:19 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pcXt4-0006fG-91 for pgsql-hackers@arkaria.postgresql.org; Wed, 15 Mar 2023 20:38:18 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pcXt3-0006f6-Rm for pgsql-hackers@lists.postgresql.org; Wed, 15 Mar 2023 20:38:17 +0000 Received: from mail-wr1-x42a.google.com ([2a00:1450:4864:20::42a]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pcXt1-0006PD-0b for pgsql-hackers@postgresql.org; Wed, 15 Mar 2023 20:38:17 +0000 Received: by mail-wr1-x42a.google.com with SMTP id j2so18435017wrh.9 for ; Wed, 15 Mar 2023 13:38:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=garret-ru.20210112.gappssmtp.com; s=20210112; t=1678912692; h=subject:from:to:content-language:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=C3nClGyD/Vxxxo6xnqmXk+OjAt3j8qZ2VYtJWuRF8Cc=; b=MN9HB0/p7cmdN4O72mOp0ZTRGqavcw8M8Wd2FOMLw/84GGzjbZgvhOfu3AbxrmalZd 6XXPQbO3zBrerdhnb5OdweMU7SjF8qntrarAwkAMgtvLK69k806ZQgeNTarc8BgMaFEk wS+ncJGsIBUjdGsxZaY6e1/yjWW04CaUF4h8bmaFMMPjMwVJLLBh/xohRuZm9yEgi9X2 zMkgL+Kk7FaV3tMhoPj4KRA9ldruS/eX/uqeKnLLoOlpxAjlHS1C5/JCyCSNEP8E77X2 tddCiknyj6yn3YC7/iwAsGocFvlIjV34cQxPZkowsCbfGgXFapY4q5d7cZ7eTpQfs+Cr v/kg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1678912692; h=subject:from:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=C3nClGyD/Vxxxo6xnqmXk+OjAt3j8qZ2VYtJWuRF8Cc=; b=w8D3EfJJ1xzYSkFfhBMAuSUferYP12BYgOwEU0Rop6P5uL4Gsn9GLnQRqy9HcgdPx7 46eQT0XApCHrj7PFAtZUg3fWHWlmOkjhDpoy8ebs6yTHJqV40Ijs+69dTU7GjVw2pwSD xtJ3kf/SpZfYhXwIUypWXs8sg2fx5DcFOHJENa50C4KUt4zozDIIoDW8U6f4YAB5Bxlz sEntfJwSmGX3QCDvz1AuewzpXCKR3YXT0EZVPkHDXpsyd2KQkg/2pNI4mM3V/u8Q/DPt BPC/FfC7GlqDLQQnRRz90OnFXjsZa4LMPDGgIK302i9tudB3zdkaGUnodD/YsOxAVejH ulXg== X-Gm-Message-State: AO0yUKWDzCwVt8aMqLVMbyW+o8T+hoEbR2cFRHSSTX8qsl2HbFUh5Orw +xInESeJtO2ZcSmVAbQs+y4mQC83OXMmNwbMR6dFrA== X-Google-Smtp-Source: AK7set9ulx6bIW5AFDeBwPfsWafDCx2yEIcAsIosUVo3BVdajkCgWfL8RZ+lL9I1DxcmD2zNijdyQw== X-Received: by 2002:a5d:5411:0:b0:2cf:e332:7fc7 with SMTP id g17-20020a5d5411000000b002cfe3327fc7mr3194348wrv.61.1678912692036; Wed, 15 Mar 2023 13:38:12 -0700 (PDT) Received: from [192.168.2.21] ([217.175.216.56]) by smtp.gmail.com with ESMTPSA id r9-20020a5d4e49000000b002c71b4d476asm5437371wrt.106.2023.03.15.13.38.09 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 15 Mar 2023 13:38:11 -0700 (PDT) Content-Type: multipart/alternative; boundary="------------xkVCmLhoFN2NdDdnlowRTP08" Message-ID: Date: Wed, 15 Mar 2023 22:38:06 +0200 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.1 Content-Language: en-US To: PostgreSQL Hackers From: Konstantin Knizhnik Subject: Speed-up shared buffers prewarming List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------xkVCmLhoFN2NdDdnlowRTP08 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi hackers, It is well known fact that queries using sequential scan can not be used to prewarm cache, because them are using ring buffer even if shared buffers are almost empty. I have searched hackers archive but failed to find any discussion about it. What are the drawbacks of using free buffers even with BAM_BULKREAD strategy? I mean the following trivial patch: diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 6be80476db..243335d0e4 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -208,8 +208,15 @@ StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state)         /*          * If given a strategy object, see whether it can select a buffer. We          * assume strategy objects don't need buffer_strategy_lock.          */ -       if (strategy != NULL) +       if (strategy != NULL && StrategyControl->firstFreeBuffer < 0)         {                 buf = GetBufferFromRing(strategy, buf_state);                 if (buf != NULL) So if there are free buffers, then use normal buffer allocation instead of GetBufferFromRing. Right now it is necessary to use pg_prewarm extension in order to prewarm buffers. But it is not convenient (you need to manually locate and prewarm all indexes and TOAST relation) and not always possible (client may just not notice that server is restarted). One potential problem which I can imagine is sync scan: when several seqscans of the same table are using the same pages from ring buffer. But synchronization of concurrent sync scans is naturally achieved: backed which is moving first is moving slowly than catching up backends which do not need to read something from the disk. It seems to me that if we allow to use all shared buffers instead of small ring buffer, then concurrent seqscans will have more chances to reuse cached pages. I have performed multiple tests with spawning multiple parallel seqscans after postgres restart and didn't observe any problems or degradation of performance comparing with master. Also ring buffer is used not only for seqscan. There are several places in Postgres core and extension (for example pgvector) where BAM_BULKREAD strategy is used also for index scan. Certainly OS file cache should prevent redundant disk reads. But it seems to be better in any case to use free memory inside Postgres process rather than rely on OS cache and perform syscalls to copy data from this cache. Definitely it is possible that seqscan limited by ring buffer will be completed faster than seqscan filling all shared buffers especially if size of shared buffers is large enough. OS will need some extra time to commit memory and may be swap out other regions to find enough physical memory for shared buffers. But if data set fits in memory, then subsequent  queries will be much faster. And it is quite common for modern servers that size of shared buffers is comparable with database size. I will be pleased you point me at some drawbacks of such approach. Otherwise I can propose patch for commitfest. --------------xkVCmLhoFN2NdDdnlowRTP08 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit Hi hackers,

It is well known fact that queries using sequential scan can not be used to prewarm cache, because them are using ring buffer
even if shared buffers are almost empty.
I have searched hackers archive but failed to find any discussion about it.
What are the drawbacks of using free buffers even with BAM_BULKREAD strategy?
I mean the following trivial patch:

diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
index 6be80476db..243335d0e4 100644
--- a/src/backend/storage/buffer/freelist.c
+++ b/src/backend/storage/buffer/freelist.c
@@ -208,8 +208,15 @@ StrategyGetBuffer(BufferAccessStrategy strategy, uint32 *buf_state)
        /*
         * If given a strategy object, see whether it can select a buffer. We
         * assume strategy objects don't need buffer_strategy_lock.
         */
-       if (strategy != NULL)
+       if (strategy != NULL && StrategyControl->firstFreeBuffer < 0)
        {
                buf = GetBufferFromRing(strategy, buf_state);
                if (buf != NULL)

So if there are free buffers, then use normal buffer allocation instead of GetBufferFromRing.

Right now it is necessary to use pg_prewarm extension in order to prewarm buffers.
But it is not convenient (you need to manually locate and prewarm all indexes and TOAST relation) and not always possible
(client may just not notice that server is restarted).

One potential problem which I can imagine is sync scan: when several seqscans of the same table are using the same pages from ring buffer.
But synchronization of concurrent sync scans is naturally achieved: backed which is moving first is moving slowly than catching up backends
which do not need to read something from the disk. It seems to me that if we allow to use all shared buffers instead of small ring buffer,
then concurrent seqscans will have more chances to reuse cached pages. I have performed multiple tests with spawning multiple parallel seqscans
after postgres restart and didn't observe any problems or degradation of performance comparing with master.

Also ring buffer is used not only for seqscan. There are several places in Postgres core and extension (for example pgvector) where BAM_BULKREAD strategy is used
also for index scan.

Certainly OS file cache should prevent redundant disk reads.
But it seems to be better in any case to use free memory inside Postgres process rather than rely on OS cache and perform syscalls to copy data from this cache.

Definitely it is possible that seqscan limited by ring buffer will be completed faster than seqscan filling all shared buffers especially if
size of shared buffers is large enough. OS will need some extra time to commit memory and may be swap out other regions to find enough physical
memory for shared buffers. But if data set fits in memory, then subsequent  queries will be much faster. And it is quite common for modern servers
that size of shared buffers is comparable with database size.

I will be pleased you point me at some drawbacks of such approach.
Otherwise I can propose patch for commitfest.
--------------xkVCmLhoFN2NdDdnlowRTP08--