Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wA69u-0023pK-1c for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Apr 2026 13:07:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wA69t-00HVVY-01 for pgsql-hackers@arkaria.postgresql.org; Tue, 07 Apr 2026 13:07:57 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wA69s-00HVN7-1P for pgsql-hackers@lists.postgresql.org; Tue, 07 Apr 2026 13:07:57 +0000 Received: from meesny.iki.fi ([195.140.195.201]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wA69q-000000016PZ-1g0O for pgsql-hackers@lists.postgresql.org; Tue, 07 Apr 2026 13:07:56 +0000 Received: from [10.0.2.15] (unknown [130.41.208.1]) (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) (Authenticated sender: hlinnaka) by meesny.iki.fi (Postfix) with ESMTPSA id 4fqmhS3ZqnzySf; Tue, 07 Apr 2026 16:07:52 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1775567273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=l74Ab4dd7/pUEOQ5YW5f1jOmbkkbzHJeJh8BrMIhEj4=; b=zN8cnW/dUXEikGwY6UrHNMwbgoDeTWrP5kyMJRkf1Rxc3TGtQSeme5k4PvVM1iz3U8Tp7Q yopShSSE7ncrK3ngPtMltaPFQRUGaij1M0Zmvcz+xMDkXzgDFAZtdqpeM3R0vKx70xUf8A F+ljiL0jhIgzmt0QhTWipK4ZYu86eVY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=iki.fi; s=meesny; t=1775567273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=l74Ab4dd7/pUEOQ5YW5f1jOmbkkbzHJeJh8BrMIhEj4=; b=KwztGi4WU0Ye1ITzAG9a6PySmkUJaq2LYTvYrVkoSiCaRPncIcfc/e2ArJaOTFoBhKFnHO GPr4BXc2y/Us9AhMuF0Bd/ybfhnh2U5lghyPGR0j4Qo/Wxt0szRW0RUmItx9N+n/odPOS6 vRfj0sV2kNNsBqffk7hWNO8iU2MSM2E= ARC-Authentication-Results: i=1; ORIGINATING; auth=pass smtp.auth=hlinnaka smtp.mailfrom=hlinnaka@iki.fi ARC-Seal: i=1; a=rsa-sha256; d=iki.fi; s=meesny; cv=none; t=1775567273; b=VneaXb92UOR+QmDcdOktiBt2xjH7Gav5PanJpkQGu+p/UMRtcbV/cUtZ8AB1hHpt/C6ho9 aCRafonzgoeueTquBXZemYC0DswGH3vCpR0CzyP9gW5SNWlub32xVRXSr4kE5vvHzK90fq /bvPczeF8t0vD/6Tn6lLm+oDUgxpv8Q= Message-ID: <7ab3914f-da59-4c1f-b809-225637b586e8@iki.fi> Date: Tue, 7 Apr 2026 16:07:45 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: pg_buffercache: Add per-relation summary stats To: Ashutosh Bapat , Tomas Vondra , chaturvedipalak1911@gmail.com Cc: Masahiko Sawada , Lukas Fittl , PostgreSQL Hackers , Paul A Jungwirth , Khoa Nguyen References: <670b867e-6518-48b0-b7c2-bd5f10ab58c6@vondra.me> Content-Language: en-US From: Heikki Linnakangas In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 28/03/2026 06:18, Ashutosh Bapat wrote: > Parallely myself and Palak Chaturvedi developed a quick patch to > modernise pg_buffercache_pages() and use tuplestore so that it doesn't > have to rely on NBuffers being the same between start of the scan, > when memory allocated, when the scan ends - a condition possible with > resizing buffer cache. It seems to improve the timings by about 10-30% > on my laptop for 128MB buffercache size. Without this patch the time > taken to execute Lukas's query varies between 10-15ms on my laptop. > With this patch it varies between 8-9ms. So the timing is more stable > as a side effect. It's not a 10x improvement that we are looking for > but it looks like a step in the right direction. That improvement > seems to come purely because we avoid creating a heap tuple. I wonder > if there are some places up in the execution tree where full > heaptuples get formed again instead of continuing to use minimal > tuples or places where we perform some extra actions that are not > required. > > I didn't dig into the history to find out why we didn't modernize > pg_buffercache_pages(). I don't see any hazard though. Committed this modernization patch, thanks! It would be nice to have a proper row-at-a-time mode that would avoid materializing the result, but collecting all the data in a temporary array is clearly worse than just putting them to the tuplestore directly. The only reason I can think of why we'd prefer to use a temporary array like that is to get a more consistent snapshot of all the buffers, by keeping the time spent scanning the buffers as short as possible. But we're not getting a consistent view anyway, it's just a matter of degree. I wondered about this in pg_buffercache_pages.c: > /* > * To smoothly support upgrades from version 1.0 of this extension > * transparently handle the (non-)existence of the pinning_backends > * column. We unfortunately have to get the result type for that... - we > * can't use the result type determined by the function definition without > * potentially crashing when somebody uses the old (or even wrong) > * function definition though. > */ > if (get_call_result_type(fcinfo, NULL, &expected_tupledesc) != TYPEFUNC_COMPOSITE) > elog(ERROR, "return type must be a row type"); > > if (expected_tupledesc->natts < NUM_BUFFERCACHE_PAGES_MIN_ELEM || > expected_tupledesc->natts > NUM_BUFFERCACHE_PAGES_ELEM) > elog(ERROR, "incorrect number of output arguments"); I guess it's still needed, if you have pg_upgraded all the way from 1.0. To test that, I created this view to match the old 1.0 definition: CREATE VIEW public.legacy_pg_buffercache AS SELECT bufferid, relfilenode, reltablespace, reldatabase, relforknumber, relblocknumber, isdirty, usagecount FROM public.pg_buffercache_pages() p(bufferid integer, relfilenode oid, reltablespace oid, reldatabase oid, relforknumber smallint, relblocknumber bigint, isdirty boolean, usagecount smallint); "select * from public.legacy_pg_buffercache" still works, so all good. - Heikki