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 1w9ZHH-001Y1T-1I for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Apr 2026 02:01:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w9ZHF-005q89-1y for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Apr 2026 02:01:22 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w9ZHF-005q80-0e for pgsql-hackers@lists.postgresql.org; Mon, 06 Apr 2026 02:01:21 +0000 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w9ZHD-00000000mTt-1tj4 for pgsql-hackers@lists.postgresql.org; Mon, 06 Apr 2026 02:01:20 +0000 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-82748257f5fso2543213b3a.1 for ; Sun, 05 Apr 2026 19:01:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775440879; x=1776045679; darn=lists.postgresql.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=pqUBVf8MY1CrUbm0fTRZVVVvtageZwFLLaTr3sDF4Go=; b=RDOdegbcC83RCLd1xZvrQ9UGO8rxHo/v7kQd1kM5nMme1wzsHkaD1sNh36cGwURgVz UcT8fcPi2tWAhHG4t6HyuTpJIMIgrv3NPpcWa7AuDUTBdjjNtQBDYUrGFw6jUn/41XMD 6onqNClzIkh/8GZ4VwRJClSmGhe4Dp8enD/gm/alwWLqbOkcE/xKqE3oQsGgqzfSndXn 0wRM26fqsmJ7f7xNpsR1pJS3jVJ9647YhZU7lopn7EfJlhz4Mz9T+hK6gY6LtSp1tEeX 7QMnLClK2OhflHKt3jfLW5wabNnnvBWDWJQeH7ZafxdP1zsiwYcMKjKVA0RPm72OHCwt BLdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775440879; x=1776045679; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-gg:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=pqUBVf8MY1CrUbm0fTRZVVVvtageZwFLLaTr3sDF4Go=; b=SyWjm/DwBAzq+N0kaLvAf+TuYFu4oqL6LY5aXZ5UQGBzY1pbXKMgV+dwBxTT0/DhCY 5WYLGF0VGIYrHnNQcJc1AKo2ldU5BLFgzT36k1r8iheOMjbIpR3KG1NWr1QIaGvwVIli V3CIZrvwY4/4IvIfk1u34xP93pcj7JRs+n/zbD+C6VJBuFcdMZ/a+u/wpNXXEHmYtMvX j0ZUs+WjWAOkWCy4roAZKt8EdmvnOU6LiFqAL+UIApfczsM5ImcTXG+68mxV2JnaKkk9 f5leTuXt/SE2u93xelzRKiOtH+VawgQ5taiDC+OjKYaF1sektXCYkwuw/VxBLxKvhnlk pD8Q== X-Forwarded-Encrypted: i=1; AJvYcCW7QunCYB73tkwzyAoyTznwt9hXEiNFctvwqWSBIlP1JetB7D7ECUIbFcglackmv60gCL8RD2Dui/jEU13j@lists.postgresql.org X-Gm-Message-State: AOJu0YxnUCeS/PMREGCAmr3WyGx2q5b0fTu4MnBzW2HaxPzzC0XRP6RM Q3ioNYDEY8GzIHDwcCaP9ElVixX7fbSfBxt/1J6bisSMvtgi3Qg1COvZ X-Gm-Gg: AeBDies7cZ4k/d9its/TT9uaTn8+FWDKk1k9S5ItA9/EXcAq92IEsnoUq3PxKJkhPAs OWVTVGzkCel5aPMwR6lRGt2GI2teBk3c+U8pLXJ3irqAK8MKfASL2UQMVSz54NerB1xzr5HkLvF Gva0AvL/sN5i4t/vA9VdeNAhgh6CVA/lLdsLLDJFTGS8hqrQ2WnceBQeRbir4Z5pd+QwefnG05r 83739SUpVXv0hdO8zSsmRXgtZTCz5qVM6OaDGM++/fWC1rjjrycK6Vaaz8k/7TJBDycSJKFuZNJ TP1DVHMNY8BpcKL0HhjsUWKDe0NSSxZeOAaq+y/HeTtJeUFcVVynt1BSmao5X1CNPlcHzM9fNq2 ARxH7eGJBAc74KUR7GBnhZSkDRav+wgNHr2EtAx14MRTF8sJAFhmJ02JFShYZz6zbHSl82I4JIG T/3Djcu05ZAnoa+PzTS0/Fys3FRbq9hC4= X-Received: by 2002:a05:6a00:2790:b0:82c:20c2:81d4 with SMTP id d2e1a72fcca58-82d003ab2fdmr11286433b3a.30.1775440878518; Sun, 05 Apr 2026 19:01:18 -0700 (PDT) Received: from smtpclient.apple ([45.32.121.103]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9b261b6sm14575884b3a.3.2026.04.05.19.01.16 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 05 Apr 2026 19:01:17 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.400.21\)) Subject: Re: Small and unlikely overflow hazard in bms_next_member() From: Chao Li In-Reply-To: Date: Mon, 6 Apr 2026 10:00:38 +0800 Cc: Tom Lane , PostgreSQL Developers Content-Transfer-Encoding: quoted-printable Message-Id: <64C19DC3-CE9B-4222-B71E-31B88574FBDC@gmail.com> References: <3190647.1775103768@sss.pgh.pa.us> <59B9EFAF-84DF-40A9-847F-9CF457A798BB@gmail.com> To: David Rowley X-Mailer: Apple Mail (2.3864.400.21) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk > On Apr 4, 2026, at 11:30, David Rowley wrote: >=20 > On Sat, 4 Apr 2026 at 02:28, Chao Li wrote: >> In test_bms_next2.c, you set words_to_alloc =3D 1, which disables the = optimization in the unrolled version. If I change words_to_alloc =3D 2, = then on my MacBook M4, the unrolled version seems to win: >> ``` >> chaol@ChaodeMacBook-Air test % ./test_bms_next2 >> Benchmarking 100000000 iterations... >>=20 >> Original: 0.61559 seconds >> David's: 0.61651 seconds >> Chao's version: 1.06033 seconds >> Unrolled loop: 0.60561 seconds >> 2800000000 >> ``` >=20 > Doing the same locally, here's what I get on my Zen2 machine: >=20 > drowley@amd3990x:~$ gcc test_bms_next.c -O2 -o test_bms_next && = ./test_bms_next > Benchmarking 100000000 iterations... >=20 > Original: 1.21125 seconds > David's: 1.11997 seconds > Chao's version: 1.72662 seconds > Unrolled loop: 1.63090 seconds > 2800000000 > drowley@amd3990x:~$ clang test_bms_next.c -O2 -o test_bms_next && > ./test_bms_next > Benchmarking 100000000 iterations... >=20 > Original: 1.10780 seconds > David's: 1.05968 seconds > Chao's version: 1.87123 seconds > Unrolled loop: 1.11002 seconds > 2800000000 I just tried my Windows laptop with both MSYS2 and WSL Ubuntu, and on = both of them the original version and David=E2=80=99s version = consistently performed better than the other versions. I have a new finding from Godbolt: adding likely(w !=3D 0) seems to = reduce the instruction count by one. bms_next_member_fast has 26 = instructions, while after adding "likely", bms_next_member_fast2 has 25. = It seems that this may avoid one jump and perhaps be slightly better, = but I=E2=80=99m not sure. I=E2=80=99m really not an expert in assembly. Then I tested. =E2=80=9Clikely=E2=80=9D doesn=E2=80=99t seem to help on = Mac: ``` chaol@ChaodeMacBook-Air test % ./test_bms_next2 Benchmarking 100000000 iterations... Original: 0.54994 seconds David's: 0.78218 seconds David's likely: 0.78990 seconds Chao's version: 1.11530 seconds Unrolled loop: 0.47660 seconds 3500000000 ``` But it helps slightly on Windows: ``` $ ./test_bms_next2 Benchmarking 100000000 iterations... Original: 1.45312 seconds David's: 1.48438 seconds David's likely: 1.40625 seconds Chao's version: 3.12500 seconds Unrolled loop: 2.95312 seconds -794967296 ``` I=E2=80=99m not suggesting adding likely() to your version, I=E2=80=99m = just sharing the information for your reference and leaving the decision = to you. >=20 >> I guess one-word Bitmapset are probably the most common case in = practice. So overall, I agree that your version is the best choice. = Please go ahead with it as we have already gained both a bug fix and a = performance improvement. If we really want to study the performance more = deeply, I think that would be a separate topic. >=20 > Yeah, but it's better to find bottlenecks and focus there than to > optimise blindly without knowing if it'll make any actual difference. > It's still important to test for regressions when modifying code and > try to avoid them, as it's sometimes not obvious if the code being > modified is critical for performance. >=20 > I also don't think we should be doing anything to optimise for > multi-word sets at the expense of slowing down single-word sets. Fully agreed. > Not > that it's very representative of the real world, but I added some > telemetry to bitmapset.c and I see 43 multi-word sets being created > and 1.45 million single-word sets created during make check, or 1 in > 33785, if you prefer. >=20 > diff --git a/src/backend/nodes/bitmapset.c = b/src/backend/nodes/bitmapset.c > index 786f343b3c9..21b5053e9a2 100644 > --- a/src/backend/nodes/bitmapset.c > +++ b/src/backend/nodes/bitmapset.c > @@ -219,6 +219,10 @@ bms_make_singleton(int x) > int wordnum, > bitnum; >=20 > + if (x >=3D 64) > + elog(NOTICE, "multi-word set bms_make_singleton"); > + else > + elog(NOTICE, "single-word set bms_make_singleton"); > if (x < 0) > elog(ERROR, "negative bitmapset member not allowed"); > wordnum =3D WORDNUM(x); > @@ -811,6 +815,9 @@ bms_add_member(Bitmapset *a, int x) > wordnum =3D WORDNUM(x); > bitnum =3D BITNUM(x); >=20 > + if (x >=3D 64 && a->nwords =3D=3D 1) > + elog(NOTICE, "multi-set bms_add_member"); > + > /* enlarge the set if necessary */ > if (wordnum >=3D a->nwords) > { >=20 > Not quite perfect as a set made first as a single word set that later > becomes a multi-word set will be double counted. The number of > operations on the sets is likely more important anyway, not the number > of sets being created. The point is, multi-word sets are rare for most > workloads. >=20 What tests did you run after adding the logs to collect the data? This = is a method I might borrow in the future for similar investigations. Best regards, -- Chao Li (Evan) HighGo Software Co., Ltd. https://www.highgo.com/