Skip to content

Commit d025cf8

Browse files
committed
Modify various power 2 calculations to use new helper functions
First pass of modifying various places that obtain the next power of 2 of a number and make them use the new functions added in pg_bitutils.h instead. This also removes the _hash_log2() function. There are no longer any callers in core. Other users can swap their _hash_log2(n) call to make use of pg_ceil_log2_32(n). Author: David Fetter, with some minor adjustments by me Reviewed-by: John Naylor, Jesse Zhang Discussion: https://postgr.es/m/20200114173553.GE32763%40fetter.org
1 parent 50a38f6 commit d025cf8

File tree

7 files changed

+32
-62
lines changed

7 files changed

+32
-62
lines changed

src/backend/access/hash/hashpage.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "access/hash.h"
3232
#include "access/hash_xlog.h"
3333
#include "miscadmin.h"
34+
#include "port/pg_bitutils.h"
3435
#include "storage/lmgr.h"
3536
#include "storage/predicate.h"
3637
#include "storage/smgr.h"
@@ -502,7 +503,7 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
502503
double dnumbuckets;
503504
uint32 num_buckets;
504505
uint32 spare_index;
505-
uint32 i;
506+
uint32 lshift;
506507

507508
/*
508509
* Choose the number of initial bucket pages to match the fill factor
@@ -542,15 +543,12 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
542543
metap->hashm_nmaps = 0;
543544
metap->hashm_ffactor = ffactor;
544545
metap->hashm_bsize = HashGetMaxBitmapSize(page);
546+
545547
/* find largest bitmap array size that will fit in page size */
546-
for (i = _hash_log2(metap->hashm_bsize); i > 0; --i)
547-
{
548-
if ((1 << i) <= metap->hashm_bsize)
549-
break;
550-
}
551-
Assert(i > 0);
552-
metap->hashm_bmsize = 1 << i;
553-
metap->hashm_bmshift = i + BYTE_TO_BIT;
548+
lshift = pg_leftmost_one_pos32(metap->hashm_bsize);
549+
Assert(lshift > 0);
550+
metap->hashm_bmsize = 1 << lshift;
551+
metap->hashm_bmshift = lshift + BYTE_TO_BIT;
554552
Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1));
555553

556554
/*
@@ -570,7 +568,7 @@ _hash_init_metabuffer(Buffer buf, double num_tuples, RegProcedure procid,
570568
* Set highmask as next immediate ((2 ^ x) - 1), which should be
571569
* sufficient to cover num_buckets.
572570
*/
573-
metap->hashm_highmask = (1 << (_hash_log2(num_buckets + 1))) - 1;
571+
metap->hashm_highmask = pg_nextpower2_32(num_buckets + 1) - 1;
574572
metap->hashm_lowmask = (metap->hashm_highmask >> 1);
575573

576574
MemSet(metap->hashm_spares, 0, sizeof(metap->hashm_spares));
@@ -659,9 +657,9 @@ _hash_expandtable(Relation rel, Buffer metabuf)
659657
*
660658
* Ideally we'd allow bucket numbers up to UINT_MAX-1 (no higher because
661659
* the calculation maxbucket+1 mustn't overflow). Currently we restrict
662-
* to half that because of overflow looping in _hash_log2() and
663-
* insufficient space in hashm_spares[]. It's moot anyway because an
664-
* index with 2^32 buckets would certainly overflow BlockNumber and hence
660+
* to half that to prevent failure of pg_ceil_log2_32() and insufficient
661+
* space in hashm_spares[]. It's moot anyway because an index with 2^32
662+
* buckets would certainly overflow BlockNumber and hence
665663
* _hash_alloc_buckets() would fail, but if we supported buckets smaller
666664
* than a disk block then this would be an independent constraint.
667665
*

src/backend/access/hash/hashsort.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "commands/progress.h"
3030
#include "miscadmin.h"
3131
#include "pgstat.h"
32+
#include "port/pg_bitutils.h"
3233
#include "utils/tuplesort.h"
3334

3435

@@ -69,7 +70,7 @@ _h_spoolinit(Relation heap, Relation index, uint32 num_buckets)
6970
* NOTE : This hash mask calculation should be in sync with similar
7071
* calculation in _hash_init_metabuffer.
7172
*/
72-
hspool->high_mask = (((uint32) 1) << _hash_log2(num_buckets + 1)) - 1;
73+
hspool->high_mask = pg_nextpower2_32(num_buckets + 1) - 1;
7374
hspool->low_mask = (hspool->high_mask >> 1);
7475
hspool->max_buckets = num_buckets - 1;
7576

src/backend/access/hash/hashutil.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "access/hash.h"
1818
#include "access/reloptions.h"
1919
#include "access/relscan.h"
20+
#include "port/pg_bitutils.h"
2021
#include "storage/buf_internals.h"
2122
#include "utils/lsyscache.h"
2223
#include "utils/rel.h"
@@ -134,21 +135,6 @@ _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
134135
return bucket;
135136
}
136137

137-
/*
138-
* _hash_log2 -- returns ceil(lg2(num))
139-
*/
140-
uint32
141-
_hash_log2(uint32 num)
142-
{
143-
uint32 i,
144-
limit;
145-
146-
limit = 1;
147-
for (i = 0; limit < num; limit <<= 1, i++)
148-
;
149-
return i;
150-
}
151-
152138
/*
153139
* _hash_spareindex -- returns spare index / global splitpoint phase of the
154140
* bucket
@@ -158,8 +144,7 @@ _hash_spareindex(uint32 num_bucket)
158144
{
159145
uint32 splitpoint_group;
160146
uint32 splitpoint_phases;
161-
162-
splitpoint_group = _hash_log2(num_bucket);
147+
splitpoint_group = pg_ceil_log2_32(num_bucket);
163148

164149
if (splitpoint_group < HASH_SPLITPOINT_GROUPS_WITH_ONE_PHASE)
165150
return splitpoint_group;

src/backend/utils/hash/dynahash.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787

8888
#include "access/xact.h"
8989
#include "common/hashfn.h"
90+
#include "port/pg_bitutils.h"
9091
#include "storage/shmem.h"
9192
#include "storage/spin.h"
9293
#include "utils/dynahash.h"
@@ -1718,16 +1719,15 @@ hash_corrupted(HTAB *hashp)
17181719
int
17191720
my_log2(long num)
17201721
{
1721-
int i;
1722-
long limit;
1723-
1724-
/* guard against too-large input, which would put us into infinite loop */
1722+
/* guard against too-large input, which would be invalid for pg_ceil_log2_*() */
17251723
if (num > LONG_MAX / 2)
17261724
num = LONG_MAX / 2;
17271725

1728-
for (i = 0, limit = 1; limit < num; i++, limit <<= 1)
1729-
;
1730-
return i;
1726+
#if SIZEOF_LONG < 8
1727+
return pg_ceil_log2_32(num);
1728+
#else
1729+
return pg_ceil_log2_64(num);
1730+
#endif
17311731
}
17321732

17331733
/* calculate first power of 2 >= num, bounded to what will fit in a long */

src/include/access/hash.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,6 @@ extern uint32 _hash_datum2hashkey(Relation rel, Datum key);
451451
extern uint32 _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype);
452452
extern Bucket _hash_hashkey2bucket(uint32 hashkey, uint32 maxbucket,
453453
uint32 highmask, uint32 lowmask);
454-
extern uint32 _hash_log2(uint32 num);
455454
extern uint32 _hash_spareindex(uint32 num_bucket);
456455
extern uint32 _hash_get_totalbuckets(uint32 splitpoint_phase);
457456
extern void _hash_checkpage(Relation rel, Buffer buf, int flags);

src/include/lib/simplehash.h

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
* backwards, unless they're empty or already at their optimal position.
5858
*/
5959

60+
#include "port/pg_bitutils.h"
61+
6062
/* helpers */
6163
#define SH_MAKE_PREFIX(a) CppConcat(a,_)
6264
#define SH_MAKE_NAME(name) SH_MAKE_NAME_(SH_MAKE_PREFIX(SH_PREFIX),name)
@@ -215,27 +217,6 @@ SH_SCOPE void SH_STAT(SH_TYPE * tb);
215217
#ifndef SIMPLEHASH_H
216218
#define SIMPLEHASH_H
217219

218-
/* FIXME: can we move these to a central location? */
219-
220-
/* calculate ceil(log base 2) of num */
221-
static inline uint64
222-
sh_log2(uint64 num)
223-
{
224-
int i;
225-
uint64 limit;
226-
227-
for (i = 0, limit = 1; limit < num; i++, limit <<= 1)
228-
;
229-
return i;
230-
}
231-
232-
/* calculate first power of 2 >= num */
233-
static inline uint64
234-
sh_pow2(uint64 num)
235-
{
236-
return ((uint64) 1) << sh_log2(num);
237-
}
238-
239220
#ifdef FRONTEND
240221
#define sh_error(...) pg_log_error(__VA_ARGS__)
241222
#define sh_log(...) pg_log_info(__VA_ARGS__)
@@ -259,7 +240,7 @@ SH_COMPUTE_PARAMETERS(SH_TYPE * tb, uint32 newsize)
259240
size = Max(newsize, 2);
260241

261242
/* round up size to the next power of 2, that's how bucketing works */
262-
size = sh_pow2(size);
243+
size = pg_nextpower2_64(size);
263244
Assert(size <= SH_MAX_SIZE);
264245

265246
/*
@@ -434,7 +415,7 @@ SH_GROW(SH_TYPE * tb, uint32 newsize)
434415
uint32 startelem = 0;
435416
uint32 copyelem;
436417

437-
Assert(oldsize == sh_pow2(oldsize));
418+
Assert(oldsize == pg_nextpower2_64(oldsize));
438419
Assert(oldsize != SH_MAX_SIZE);
439420
Assert(oldsize < newsize);
440421

src/include/port/pg_bitutils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@
1313
#ifndef PG_BITUTILS_H
1414
#define PG_BITUTILS_H
1515

16+
#ifndef FRONTEND
1617
extern PGDLLIMPORT const uint8 pg_leftmost_one_pos[256];
1718
extern PGDLLIMPORT const uint8 pg_rightmost_one_pos[256];
1819
extern PGDLLIMPORT const uint8 pg_number_of_ones[256];
20+
#else
21+
extern const uint8 pg_leftmost_one_pos[256];
22+
extern const uint8 pg_rightmost_one_pos[256];
23+
extern const uint8 pg_number_of_ones[256];
24+
#endif
1925

2026
/*
2127
* pg_leftmost_one_pos32

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy