Skip to content

Commit

Permalink
FIXME enable 64bit bitmapset and update visimap (#14784)
Browse files Browse the repository at this point in the history
It includes the portion about enabling 64bit bms and other necessary
changes related to visimap, plus updates of cmockery unit tests.
  • Loading branch information
yaowangm authored and yjhjstz committed Jan 6, 2025
1 parent 6584d1b commit a03d2b8
Show file tree
Hide file tree
Showing 7 changed files with 381 additions and 51 deletions.
47 changes: 32 additions & 15 deletions src/backend/access/appendonly/appendonly_visimap_entry.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ AppendOnlyVisimap_GetAttrNotNull(HeapTuple t, TupleDesc td, int attr)
void
AppendOnlyVisiMapEnty_ReadData(AppendOnlyVisimapEntry *visiMapEntry, size_t dataSize)
{
int newWordCount;
/* the block count of (ondisk) bitstream */
int onDiskBlockCount;
/* the word count of in-memory bitmapset */
int bmsWordCount;

Assert(visiMapEntry);
Assert(CurrentMemoryContext == visiMapEntry->memoryContext);
Expand All @@ -156,21 +159,23 @@ AppendOnlyVisiMapEnty_ReadData(AppendOnlyVisimapEntry *visiMapEntry, size_t data
* but I think it is reasonable to set it to NULLL to avoid similar issues.
*/
visiMapEntry->bitmap = NULL;
newWordCount =
BitmapDecompress_GetBlockCount(&decompressState);
if (newWordCount > 0)
BitmapDecompress_CalculateBlockCounts(&decompressState,
&onDiskBlockCount,
&bmsWordCount);

if (onDiskBlockCount > 0)
{
visiMapEntry->bitmap = palloc0(offsetof(Bitmapset, words) +
(newWordCount * sizeof(bitmapword)));
visiMapEntry->bitmap->nwords = newWordCount;
(bmsWordCount * sizeof(bitmapword)));
visiMapEntry->bitmap->nwords = bmsWordCount;
BitmapDecompress_Decompress(&decompressState,
visiMapEntry->bitmap->words,
newWordCount);
(uint32 *)visiMapEntry->bitmap->words,
onDiskBlockCount);
}
else if (newWordCount != 0)
else if (onDiskBlockCount != 0)
{
elog(ERROR,
"illegal visimap block count: visimap block count %d", newWordCount);
"illegal visimap block count: visimap block count %d", onDiskBlockCount);
}

}
Expand Down Expand Up @@ -264,23 +269,32 @@ AppendOnlyVisimapEntry_GetHiddenTupleCount(
void
AppendOnlyVisimapEntry_WriteData(AppendOnlyVisimapEntry *visiMapEntry)
{
int bitmapSize,
compressedBitmapSize;
/* bitmap size, in bytes */
int bitmapSize;
int compressedBitmapSize;
/* word count in 64bit or 32bit words for in-memory bms */
int bmsWordCount;
/* block count always in 32bit (after conversion if necessary) */
int blockCount;

Assert(visiMapEntry);
Assert(CurrentMemoryContext == visiMapEntry->memoryContext);
Assert(AppendOnlyVisimapEntry_IsValid(visiMapEntry));

bitmapSize = (visiMapEntry->bitmap ? (visiMapEntry->bitmap->nwords * sizeof(bitmapword)) : 0);
BitmapCompress_CalculateBlockCounts(visiMapEntry->bitmap,
&blockCount,
&bmsWordCount);
bitmapSize = sizeof(uint32) * blockCount;
bitmapSize += BITMAP_COMPRESSION_HEADER_SIZE;
Assert(bmsWordCount <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT);

Assert(visiMapEntry->data);
Assert(APPENDONLY_VISIMAP_DATA_BUFFER_SIZE >= bitmapSize);
visiMapEntry->data->version = 1;

compressedBitmapSize = Bitmap_Compress(BITMAP_COMPRESSION_TYPE_DEFAULT,
(visiMapEntry->bitmap ? visiMapEntry->bitmap->words : NULL),
(visiMapEntry->bitmap ? visiMapEntry->bitmap->nwords : 0),
(visiMapEntry->bitmap ? (uint32*)visiMapEntry->bitmap->words : NULL),
blockCount,
visiMapEntry->data->data,
bitmapSize);
Assert(compressedBitmapSize >= BITMAP_COMPRESSION_HEADER_SIZE);
Expand Down Expand Up @@ -499,6 +513,9 @@ AppendOnlyVisimapEntry_GetMinimalSizeToCover(int64 offset)
minSize |= minSize >> 8;
minSize |= minSize >> 16;
minSize++;

Assert(minSize <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT);

return minSize;
}

Expand Down
3 changes: 0 additions & 3 deletions src/backend/nodes/bitmapset.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)

#define BITMAPSET_SIZE(nwords) \
(offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))

/*----------
* This is a well-known cute trick for isolating the rightmost one-bit
* in a word. It assumes two's complement arithmetic. Consider any
Expand Down
114 changes: 111 additions & 3 deletions src/backend/utils/misc/bitmap_compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "utils/bitmap_compression.h"
#include "utils/bitstream.h"
#include "utils/guc.h"
#include "access/appendonly_visimap.h"

typedef enum BitmapCompressionFlag
{
Expand Down Expand Up @@ -80,9 +81,15 @@ BitmapDecompress_HasError(
}

/*
* Performs the bitmap decompression.
* Perform bitmap decompression into in-memory buffer
*
* bitmapDataSize in uint32-words.
* bitmap: caller-allocated buffer that can hold state->blockCount
* number of 32-bit on-disk bitmap words.
*
* For both 32-bit and 64-bit in-memory bitmap word sizes, we write
* 32-bit words into the in-memory buffer contiguously. This is safe
* to do as we interpret two contiguous 32-bit words as one 64-bit
* word.
*/
void
BitmapDecompress_Decompress(BitmapDecompressState *state,
Expand All @@ -105,7 +112,7 @@ BitmapDecompress_Decompress(BitmapDecompressState *state,

if (state->compressionType == BITMAP_COMPRESSION_TYPE_NO)
{
memcpy(bitmap,
memcpy(bitmap,
Bitstream_GetAlignedData(&state->bitstream, 16),
state->blockCount * sizeof(uint32));
}
Expand Down Expand Up @@ -357,3 +364,104 @@ Bitmap_Compress(
return 0;
}
}

/*
* Calculate two counts for decompress:
* 1. 'onDiskBlockCount': the block count of (ondisk) bitstream
* 2. 'bmsWordCount': the word count of in-memory bitmapset
*/
void BitmapDecompress_CalculateBlockCounts(BitmapDecompressState *decompressState,
int *onDiskBlockCount,
int *bmsWordCount)
{
*onDiskBlockCount =
BitmapDecompress_GetBlockCount(decompressState);

/* The on-disk bitmap representation always uses 32-bit block size
* (for backward compatibility). Depending on the environment, we
* may be using either 64-bit words or 32-bit words for the
* in-memory representation.
* So, if (in-memory) bitmapset uses 64 bit words, we can use half
* of the on-disk bitmap block count.
*/
if (BITS_PER_BITMAPWORD == 64)
{
/*
* Number of on-disk blocks is always 0, 1 or even.
* See resizing logic in AppendOnlyVisimapEntry_HideTuple()
*/
if (*onDiskBlockCount == 1)
*bmsWordCount = 1;
else
{
Assert(*onDiskBlockCount % 2 == 0);
*bmsWordCount = *onDiskBlockCount / 2;
}
}
else
{
Assert(BITS_PER_BITMAPWORD == 32);
*bmsWordCount = *onDiskBlockCount;
}
Assert(*bmsWordCount <= APPENDONLY_VISIMAP_MAX_BITMAP_WORD_COUNT);
Assert(*bmsWordCount >= 0);
}

/*
* Calculate two counts for compress:
* 1. 'onDiskBlockCount': the block count of (ondisk) bitstream
* 2. 'bmsWordCount': the word count of in-memory bitmapset
*/
void BitmapCompress_CalculateBlockCounts(Bitmapset *bitmap,
int *onDiskBlockCount,
int *bmsWordCount)
{
*onDiskBlockCount = 0;
*bmsWordCount = 0;

if (bitmap)
{
*bmsWordCount = bitmap->nwords;

/*
* On 64bit env, there is a conflict: in-memory bms is in 64bit word,
* but on-disk block is in 32bit word to keep consistency. We need to
* provide 32bit block count to Bitmap_Compress() after kind of
* conversion.
*/
if (BITS_PER_BITMAPWORD == 64)
{
/*
* On 64bit env, if there is only one 64 bit word in memory, and the
* 32 higher order bits of that word are all zero, it implies that
* there is only one 32 bit word. We can always assume that the 32
* higher order bits for a 64 bit bitmap word is zeroed out - this
* is ensured by routines such as bms_add_member() and
* AppendOnlyVisiMapEnty_ReadData().
*/
if (*bmsWordCount == 1
&& (bitmap->words[0] >> 32) == 0)
{
*onDiskBlockCount = 1;
}
else
{
/*
* onDiskBlockCount required by Bitmap_Compress() is always in
* uint32-words. So, if bitmapset uses 64 bit words, double
* the value of bmsWordCount.
*/
*onDiskBlockCount = bitmap->nwords * 2;
}
}
else
{
Assert(BITS_PER_BITMAPWORD == 32);

/*
* On 32bit env, onDiskBlockCount is always equal to bmsWordCount.
*/
*onDiskBlockCount = bitmap->nwords;
}
}
}
Loading

0 comments on commit a03d2b8

Please sign in to comment.