public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH v27 5/5] Doc: Add Collation Versions section.
3+ messages / 2 participants
[nested] [flat]

* [PATCH v27 5/5] Doc: Add Collation Versions section.
@ 2020-03-11 02:01 Thomas Munro <[email protected]>
  0 siblings, 0 replies; 3+ messages in thread

From: Thomas Munro @ 2020-03-11 02:01 UTC (permalink / raw)

Supply a brief introduction to collation version concepts.

Author: Thomas Munro <[email protected]>
Reviewed-by: Julien Rouhaud <[email protected]>
Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com
---
 doc/src/sgml/charset.sgml | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml
index 4b4563c5b9..12a82ff18c 100644
--- a/doc/src/sgml/charset.sgml
+++ b/doc/src/sgml/charset.sgml
@@ -948,6 +948,41 @@ CREATE COLLATION ignore_accents (provider = icu, locale = 'und-u-ks-level1-kc-tr
     </tip>
    </sect3>
   </sect2>
+
+  <sect2 id="collation-versions">
+   <title>Collation Versions</title>
+
+   <para>
+    The ordering defined by a collation is not necessarily fixed over time.
+    If a collation changes for any reason, persistent data structures such as
+    b-trees that depend on a stable ordering of text might be corrupted.
+    <productname>PostgreSQL</productname> defends against this by recording
+    the current version of each referenced collation for any index that
+    depends on it in the
+    <link linkend="catalog-pg-depend"><structname>pg_depend</structname></link>
+    catalog, if the collation provider makes it available.  If the provider
+    later begins to report a different version, a warning will be issued
+    when the index is accessed, until either the <xref linkend="sql-reindex"/>
+    or the <xref linkend="sql-alterindex"/> command is used to update the
+    version.
+   </para>
+   <para>
+    Version information is available for collations from the
+    <literal>icu</literal> provider on all operating systems.  For the
+    <literal>libc</literal> provider, versions are currently only available
+    on systems using the GNU C library (most Linux systems).
+   </para>
+
+   <note>
+    <para>
+     When using the GNU C library for collations, the C library's version
+     is used as a proxy for the collation version.  Many Linux distributions
+     change collation definitions only when upgrading the C library, but this
+     approach is imperfect as maintainers are free to back-port newer
+     collation definitions to older C library releases.
+    </para>
+   </note>
+  </sect2>
  </sect1>
 
  <sect1 id="multibyte">
-- 
2.20.1


--o56keubw4jpehgac--





^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Using pg_bitutils.h in tidbitmap.c.
@ 2025-04-14 12:41 Thomas Munro <[email protected]>
  2025-04-24 01:47 ` Re: Using pg_bitutils.h in tidbitmap.c. John Naylor <[email protected]>
  0 siblings, 1 reply; 3+ messages in thread

From: Thomas Munro @ 2025-04-14 12:41 UTC (permalink / raw)
  To: pgsql-hackers

tidbitmap.c's operations loop over all the bits, but could leap over
zeros with bitmap instructions like bitmapset.c.  Hard to imagine that
matters, but I think it also comes out easier to read?


Attachments:

  [text/x-patch] 0001-Use-pg_bitutils.h-in-tidbitmap.c.patch (4.8K, ../../CA+hUKGLRN4_8sPHrwr4HDRV-_+_MddOyJ_Wc=2C2j6Hc0kkNig@mail.gmail.com/2-0001-Use-pg_bitutils.h-in-tidbitmap.c.patch)
  download | inline diff:
From 7eec670224270c098c2fb3ad4b7748b0769a1e95 Mon Sep 17 00:00:00 2001
From: Thomas Munro <[email protected]>
Date: Wed, 19 Mar 2025 02:38:26 +1300
Subject: [PATCH] Use pg_bitutils.h in tidbitmap.c.

Instead of looping over every bit, skip the zeros.
---
 src/backend/nodes/tidbitmap.c | 108 ++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 51 deletions(-)

diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 41031aa8f2f..6ca01bdb772 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -44,6 +44,7 @@
 #include "common/int.h"
 #include "nodes/bitmapset.h"
 #include "nodes/tidbitmap.h"
+#include "port/pg_bitutils.h"
 #include "storage/lwlock.h"
 #include "utils/dsa.h"
 
@@ -242,6 +243,20 @@ static int	tbm_shared_comparator(const void *left, const void *right,
 #include "lib/simplehash.h"
 
 
+/*
+ * Return the position of the rightmost bit of *word, and also clear that bit.
+ * Useful for looping over the ones in a word.  *word must not be zero.
+ */
+static inline int
+bmw_pop_rightmost_one(bitmapword *word)
+{
+	int			position = bmw_rightmost_one_pos(*word);
+
+	*word &= ~((bitmapword) 1 << position);
+
+	return position;
+}
+
 /*
  * tbm_create - create an initially-empty bitmap
  *
@@ -474,24 +489,20 @@ tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage)
 
 	if (bpage->ischunk)
 	{
+		BlockNumber blockno = bpage->blockno;
+
 		/* Scan b's chunk, mark each indicated page lossy in a */
 		for (wordnum = 0; wordnum < WORDS_PER_CHUNK; wordnum++)
 		{
 			bitmapword	w = bpage->words[wordnum];
 
-			if (w != 0)
+			while (w != 0)
 			{
-				BlockNumber pg;
+				int			bitnum = bmw_pop_rightmost_one(&w);
 
-				pg = bpage->blockno + (wordnum * BITS_PER_BITMAPWORD);
-				while (w != 0)
-				{
-					if (w & 1)
-						tbm_mark_page_lossy(a, pg);
-					pg++;
-					w >>= 1;
-				}
+				tbm_mark_page_lossy(a, blockno + bitnum);
 			}
+			blockno += BITS_PER_BITMAPWORD;
 		}
 	}
 	else if (tbm_page_is_lossy(a, bpage->blockno))
@@ -584,38 +595,29 @@ tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b)
 	{
 		/* Scan each bit in chunk, try to clear */
 		bool		candelete = true;
+		BlockNumber blockno = apage->blockno;
 
 		for (wordnum = 0; wordnum < WORDS_PER_CHUNK; wordnum++)
 		{
 			bitmapword	w = apage->words[wordnum];
+			bitmapword	neww = w;
 
-			if (w != 0)
+			while (w != 0)
 			{
-				bitmapword	neww = w;
-				BlockNumber pg;
-				int			bitnum;
+				int			bitnum = bmw_pop_rightmost_one(&w);
+				BlockNumber pg = blockno + bitnum;
 
-				pg = apage->blockno + (wordnum * BITS_PER_BITMAPWORD);
-				bitnum = 0;
-				while (w != 0)
+				if (!tbm_page_is_lossy(b, pg) &&
+					tbm_find_pageentry(b, pg) == NULL)
 				{
-					if (w & 1)
-					{
-						if (!tbm_page_is_lossy(b, pg) &&
-							tbm_find_pageentry(b, pg) == NULL)
-						{
-							/* Page is not in b at all, lose lossy bit */
-							neww &= ~((bitmapword) 1 << bitnum);
-						}
-					}
-					pg++;
-					bitnum++;
-					w >>= 1;
+					/* Page is not in b at all, lose lossy bit */
+					neww &= ~((bitmapword) 1 << bitnum);
 				}
-				apage->words[wordnum] = neww;
-				if (neww != 0)
-					candelete = false;
 			}
+			apage->words[wordnum] = neww;
+			if (neww != 0)
+				candelete = false;
+			blockno += BITS_PER_BITMAPWORD;
 		}
 		return candelete;
 	}
@@ -910,21 +912,14 @@ tbm_extract_page_tuple(TBMIterateResult *iteritem,
 	{
 		bitmapword	w = page->words[wordnum];
 
-		if (w != 0)
+		while (w != 0)
 		{
-			int			off = wordnum * BITS_PER_BITMAPWORD + 1;
+			int			bitnum = bmw_pop_rightmost_one(&w);
+			int			off = wordnum * BITS_PER_BITMAPWORD + bitnum + 1;
 
-			while (w != 0)
-			{
-				if (w & 1)
-				{
-					if (ntuples < max_offsets)
-						offsets[ntuples] = (OffsetNumber) off;
-					ntuples++;
-				}
-				off++;
-				w >>= 1;
-			}
+			if (ntuples < max_offsets)
+				offsets[ntuples] = off;
+			ntuples++;
 		}
 	}
 
@@ -938,18 +933,29 @@ static inline void
 tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp)
 {
 	int			schunkbit = *schunkbitp;
+	int			wordnum = WORDNUM(schunkbit);
+	int			bitnum = BITNUM(schunkbit);
+	bitmapword	w;
+
+	/* Chop off bits to the right of bitnum in starting word. */
+	w = chunk->words[wordnum] & ~((bitmapword) 0) << bitnum;
 
-	while (schunkbit < PAGES_PER_CHUNK)
+	for (;;)
 	{
-		int			wordnum = WORDNUM(schunkbit);
-		int			bitnum = BITNUM(schunkbit);
+		if (w != 0)
+		{
+			*schunkbitp =
+				wordnum * BITS_PER_BITMAPWORD + bmw_rightmost_one_pos(w);
+			return;
+		}
 
-		if ((chunk->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
+		if (++wordnum == WORDS_PER_CHUNK)
 			break;
-		schunkbit++;
+		w = chunk->words[wordnum];
 	}
 
-	*schunkbitp = schunkbit;
+	/* No bits found.  Point past end. */
+	*schunkbitp = WORDS_PER_CHUNK * BITS_PER_BITMAPWORD;
 }
 
 /*
-- 
2.39.5



^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: Using pg_bitutils.h in tidbitmap.c.
  2025-04-14 12:41 Using pg_bitutils.h in tidbitmap.c. Thomas Munro <[email protected]>
@ 2025-04-24 01:47 ` John Naylor <[email protected]>
  0 siblings, 0 replies; 3+ messages in thread

From: John Naylor @ 2025-04-24 01:47 UTC (permalink / raw)
  To: Thomas Munro <[email protected]>; +Cc: pgsql-hackers

On Mon, Apr 14, 2025 at 7:42 PM Thomas Munro <[email protected]> wrote:
>
> tidbitmap.c's operations loop over all the bits, but could leap over
> zeros with bitmap instructions like bitmapset.c.  Hard to imagine that
> matters, but I think it also comes out easier to read?

Interesting idea -- I toyed with something like this when TID store
was being developed. Most of it looks more readable at a glance,
although tbm_advance_schunkbit() may be a wash.

+bmw_pop_rightmost_one(bitmapword *word)
+{
+ int position = bmw_rightmost_one_pos(*word);
+
+ *word &= ~((bitmapword) 1 << position);
+
+ return position;
+}

There's a more succinct way to write the second statement, since here
we only care about the rightmost bit:

*word &= *word - 1;

That has a bonus in that we don't need to know "position" beforehand,
so the CPU can schedule that independently of the bitscan, which is 3
or 4 cycles on modern hardware, but like you said, I'm not sure if
that matters.

-- 
John Naylor
Amazon Web Services





^ permalink  raw  reply  [nested|flat] 3+ messages in thread


end of thread, other threads:[~2025-04-24 01:47 UTC | newest]

Thread overview: 3+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2020-03-11 02:01 [PATCH v27 5/5] Doc: Add Collation Versions section. Thomas Munro <[email protected]>
2025-04-14 12:41 Using pg_bitutils.h in tidbitmap.c. Thomas Munro <[email protected]>
2025-04-24 01:47 ` Re: Using pg_bitutils.h in tidbitmap.c. John Naylor <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox