v20250107-0005-Collect-and-print-compression-stats.patch
text/x-patch
Filename: v20250107-0005-Collect-and-print-compression-stats.patch
Type: text/x-patch
Part: 4
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v20250107-0005
Subject: Collect and print compression stats
| File | + | − |
|---|---|---|
| src/backend/access/gin/gininsert.c | 30 | 6 |
| src/include/access/gin.h | 2 | 0 |
From ac5bb4302d74efb0d4a69a7bd623206ab5c30e70 Mon Sep 17 00:00:00 2001 From: Tomas Vondra <tomas.vondra@postgresql.org> Date: Thu, 2 May 2024 15:21:43 +0200 Subject: [PATCH v20250107 05/10] Collect and print compression stats Allows evaluating the benefits of compressing the TID lists. --- src/backend/access/gin/gininsert.c | 36 +++++++++++++++++++++++++----- src/include/access/gin.h | 2 ++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index 66f489abcab..1fc67ca1b8f 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -191,7 +191,8 @@ static void _gin_parallel_scan_and_build(GinBuildState *buildstate, static ItemPointer _gin_parse_tuple_items(GinTuple *a); static Datum _gin_parse_tuple_key(GinTuple *a); -static GinTuple *_gin_build_tuple(OffsetNumber attrnum, unsigned char category, +static GinTuple *_gin_build_tuple(GinBuildState *state, + OffsetNumber attrnum, unsigned char category, Datum key, int16 typlen, bool typbyval, ItemPointerData *items, uint32 nitems, Size *len); @@ -554,7 +555,7 @@ ginBuildCallbackParallel(Relation index, ItemPointer tid, Datum *values, /* there could be many entries, so be willing to abort here */ CHECK_FOR_INTERRUPTS(); - tup = _gin_build_tuple(attnum, category, + tup = _gin_build_tuple(buildstate, attnum, category, key, attr->attlen, attr->attbyval, list, nlist, &tuplen); @@ -1642,6 +1643,15 @@ _gin_process_worker_data(GinBuildState *state, Tuplesortstate *worker_sort) /* sort the raw per-worker data */ tuplesort_performsort(state->bs_worker_sort); + /* print some basic info */ + elog(LOG, "_gin_parallel_scan_and_build raw %zu compressed %zu ratio %.2f%%", + state->buildStats.sizeRaw, state->buildStats.sizeCompressed, + (100.0 * state->buildStats.sizeCompressed) / state->buildStats.sizeRaw); + + /* reset before the second phase */ + state->buildStats.sizeCompressed = 0; + state->buildStats.sizeRaw = 0; + /* * Read the GIN tuples from the shared tuplesort, sorted by the key, and * merge them into larger chunks for the leader to combine. @@ -1668,7 +1678,7 @@ _gin_process_worker_data(GinBuildState *state, Tuplesortstate *worker_sort) */ AssertCheckItemPointers(buffer, true); - ntup = _gin_build_tuple(buffer->attnum, buffer->category, + ntup = _gin_build_tuple(state, buffer->attnum, buffer->category, buffer->key, buffer->typlen, buffer->typbyval, buffer->items, buffer->nitems, &ntuplen); @@ -1695,7 +1705,7 @@ _gin_process_worker_data(GinBuildState *state, Tuplesortstate *worker_sort) AssertCheckItemPointers(buffer, true); - ntup = _gin_build_tuple(buffer->attnum, buffer->category, + ntup = _gin_build_tuple(state, buffer->attnum, buffer->category, buffer->key, buffer->typlen, buffer->typbyval, buffer->items, buffer->nitems, &ntuplen); @@ -1710,6 +1720,11 @@ _gin_process_worker_data(GinBuildState *state, Tuplesortstate *worker_sort) /* relase all the memory */ GinBufferFree(buffer); + /* print some basic info */ + elog(LOG, "_gin_process_worker_data raw %zu compressed %zu ratio %.2f%%", + state->buildStats.sizeRaw, state->buildStats.sizeCompressed, + (100.0 * state->buildStats.sizeCompressed) / state->buildStats.sizeRaw); + tuplesort_end(worker_sort); } @@ -1782,7 +1797,7 @@ _gin_parallel_scan_and_build(GinBuildState *state, /* there could be many entries, so be willing to abort here */ CHECK_FOR_INTERRUPTS(); - tup = _gin_build_tuple(attnum, category, + tup = _gin_build_tuple(state, attnum, category, key, attr->attlen, attr->attbyval, list, nlist, &len); @@ -1876,6 +1891,7 @@ _gin_parallel_build_main(dsm_segment *seg, shm_toc *toc) /* initialize the GIN build state */ initGinState(&buildstate.ginstate, indexRel); buildstate.indtuples = 0; + /* XXX Shouldn't this initialize the other fields too, like ginbuild()? */ memset(&buildstate.buildStats, 0, sizeof(GinStatsData)); /* @@ -1953,7 +1969,8 @@ typedef struct * of that into the GIN tuple. */ static GinTuple * -_gin_build_tuple(OffsetNumber attrnum, unsigned char category, +_gin_build_tuple(GinBuildState *state, + OffsetNumber attrnum, unsigned char category, Datum key, int16 typlen, bool typbyval, ItemPointerData *items, uint32 nitems, Size *len) @@ -2087,6 +2104,13 @@ _gin_build_tuple(OffsetNumber attrnum, unsigned char category, pfree(seginfo); } + /* how large would the tuple be without compression? */ + state->buildStats.sizeRaw += MAXALIGN(offsetof(GinTuple, data) + keylen) + + nitems * sizeof(ItemPointerData); + + /* compressed size */ + state->buildStats.sizeCompressed += tuplen; + return tuple; } diff --git a/src/include/access/gin.h b/src/include/access/gin.h index 2debdac0f43..c1938d0b9c6 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -49,6 +49,8 @@ typedef struct GinStatsData BlockNumber nDataPages; int64 nEntries; int32 ginVersion; + Size sizeRaw; + Size sizeCompressed; } GinStatsData; /* -- 2.47.1