v20251001-0023-experimental-zstd-compression.patch
text/x-patch
Filename: v20251001-0023-experimental-zstd-compression.patch
Type: text/x-patch
Part: 22
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 v20251001-0023
Subject: experimental: zstd compression
| File | + | − |
|---|---|---|
| src/backend/storage/file/buffile.c | 50 | 0 |
| src/backend/utils/misc/guc_tables.c | 3 | 0 |
| src/include/storage/buffile.h | 2 | 1 |
From 4a2c3e72a646f51d1a2527e1dc486bc33b944fcc Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@vondra.me>
Date: Wed, 1 Oct 2025 02:44:37 +0200
Subject: [PATCH v20251001 23/25] experimental: zstd compression
---
src/backend/storage/file/buffile.c | 50 +++++++++++++++++++++++++++++
src/backend/utils/misc/guc_tables.c | 3 ++
src/include/storage/buffile.h | 3 +-
3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/src/backend/storage/file/buffile.c b/src/backend/storage/file/buffile.c
index 380537fb126..cdb3f150ebf 100644
--- a/src/backend/storage/file/buffile.c
+++ b/src/backend/storage/file/buffile.c
@@ -64,11 +64,16 @@
#include <zlib.h>
#endif
+#ifdef USE_ZSTD
+#include <zstd.h>
+#endif
+
/* Compression types */
#define TEMP_NONE_COMPRESSION 0
#define TEMP_PGLZ_COMPRESSION 1
#define TEMP_LZ4_COMPRESSION 2
#define TEMP_GZIP_COMPRESSION 3
+#define TEMP_ZSTD_COMPRESSION 4
/*
* We break BufFiles into gigabyte-sized segments, regardless of RELSEG_SIZE.
@@ -308,6 +313,14 @@ BufFileCreateCompressTemp(bool interXact)
break;
}
+ case TEMP_ZSTD_COMPRESSION:
+ {
+#ifdef USE_ZSTD
+ size = ZSTD_COMPRESSBOUND(BLCKSZ) + sizeof(CompressHeader);
+#endif
+ break;
+ }
+
case TEMP_PGLZ_COMPRESSION:
size = pglz_maximum_compressed_size(BLCKSZ, BLCKSZ) + sizeof(CompressHeader);
break;
@@ -704,6 +717,7 @@ BufFileLoadBuffer(BufFile *file)
break;
case TEMP_GZIP_COMPRESSION:
+ {
#ifdef HAVE_LIBZ
int ret;
size_t len = sizeof(file->buffer);
@@ -716,7 +730,21 @@ BufFileLoadBuffer(BufFile *file)
file->nbytes = len;
#endif
break;
+ }
+ case TEMP_ZSTD_COMPRESSION:
+ {
+#ifdef USE_ZSTD
+ size_t ret;
+
+ ret = ZSTD_decompress(file->buffer.data, sizeof(file->buffer),
+ buff, header.len);
+ if (ZSTD_isError(ret))
+ elog(ERROR, "ZSTD_decompress failed");
+ file->nbytes = ret;
+#endif
+ break;
+ }
case TEMP_PGLZ_COMPRESSION:
file->nbytes = pglz_decompress(buff, header.len,
file->buffer.data, header.raw_len, false);
@@ -835,6 +863,28 @@ BufFileDumpBuffer(BufFile *file)
}
cSize = len;
+#endif
+ break;
+ }
+ case TEMP_ZSTD_COMPRESSION:
+ {
+#ifdef USE_ZSTD
+ size_t ret;
+ size_t len = ZSTD_compressBound(file->nbytes);
+
+ /* XXX maybe lower level? the default is pretty slow ... */
+ ret = ZSTD_compress(cData + sizeof(CompressHeader), len,
+ file->buffer.data, file->nbytes,
+ ZSTD_defaultCLevel());
+ if (ZSTD_isError(ret))
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_DATA_CORRUPTED),
+ errmsg_internal("compression failed, compressed size %d, original size %d",
+ cSize, nbytesOriginal)));
+ }
+
+ cSize = ret;
#endif
break;
}
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 88fbe405d59..9410e31ce00 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -476,6 +476,9 @@ static const struct config_enum_entry temp_file_compression_options[] = {
#endif
#ifdef HAVE_LIBZ
{"gzip", TEMP_GZIP_COMPRESSION, false},
+#endif
+#ifdef USE_ZSTD
+ {"zstd", TEMP_ZSTD_COMPRESSION, false},
#endif
{NULL, 0, false}
};
diff --git a/src/include/storage/buffile.h b/src/include/storage/buffile.h
index 7a1bb1d6085..ac6fe602939 100644
--- a/src/include/storage/buffile.h
+++ b/src/include/storage/buffile.h
@@ -37,7 +37,8 @@ typedef enum
TEMP_NONE_COMPRESSION,
TEMP_PGLZ_COMPRESSION,
TEMP_LZ4_COMPRESSION,
- TEMP_GZIP_COMPRESSION
+ TEMP_GZIP_COMPRESSION,
+ TEMP_ZSTD_COMPRESSION
} TempCompression;
extern PGDLLIMPORT int temp_file_compression;
--
2.51.0