From f1db87ac361a43e4758a25c982ba4008ba290ce4 Mon Sep 17 00:00:00 2001 From: Konstantin Knizhnik Date: Wed, 5 Jul 2023 11:40:38 +0300 Subject: [PATCH] Check if there is enough memory for HNSW index (#4602) ## Problem HNSW index is created in memory. Try to prevent OOM by checking of available RAM. ## Summary of changes ## Checklist before requesting a review - [ ] I have performed a self-review of my code. - [ ] If it is a core feature, I have added thorough tests. - [ ] Do we need to implement analytics? if so did you add the relevant metrics to the dashboard? - [ ] If this PR requires public announcement, mark it with /release-notes label and add several sentences in this section. ## Checklist before merging - [ ] Do not forget to reformat commit message to not include the above checklist --------- Co-authored-by: Konstantin Knizhnik --- pgxn/hnsw/hnsw.c | 39 +++++++++++++++++++++++++++++++++++++++ pgxn/hnsw/hnsw.control | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pgxn/hnsw/hnsw.c b/pgxn/hnsw/hnsw.c index 434f4986f8..45bf78ed3b 100644 --- a/pgxn/hnsw/hnsw.c +++ b/pgxn/hnsw/hnsw.c @@ -122,6 +122,43 @@ hnsw_populate(HierarchicalNSW* hnsw, Relation indexRel, Relation heapRel) true, true, hnsw_build_callback, (void *) hnsw, NULL); } +#ifdef __APPLE__ + +#include +#include + +static void +hnsw_check_available_memory(Size requested) +{ + size_t total; + if (sysctlbyname("hw.memsize", NULL, &total, NULL, 0) < 0) + elog(ERROR, "Failed to get amount of RAM: %m"); + + if ((Size)NBuffers*BLCKSZ + requested >= total) + elog(ERROR, "HNSW index requeries %ld bytes while only %ld are available", + requested, total - (Size)NBuffers*BLCKSZ); +} + +#else + +#include + +static void +hnsw_check_available_memory(Size requested) +{ + struct sysinfo si; + Size total; + if (sysinfo(&si) < 0) + elog(ERROR, "Failed to get amount of RAM: %n"); + + total = si.totalram*si.mem_unit; + if ((Size)NBuffers*BLCKSZ + requested >= total) + elog(ERROR, "HNSW index requeries %ld bytes while only %ld are available", + requested, total - (Size)NBuffers*BLCKSZ); +} + +#endif + static HierarchicalNSW* hnsw_get_index(Relation indexRel, Relation heapRel) { @@ -156,6 +193,8 @@ hnsw_get_index(Relation indexRel, Relation heapRel) size_data_per_element = size_links_level0 + data_size + sizeof(label_t); shmem_size = hnsw_sizeof() + maxelements * size_data_per_element; + hnsw_check_available_memory(shmem_size); + /* first try to attach to existed index */ if (!dsm_impl_op(DSM_OP_ATTACH, handle, 0, &impl_private, &mapped_address, &mapped_size, DEBUG1)) diff --git a/pgxn/hnsw/hnsw.control b/pgxn/hnsw/hnsw.control index b292b96026..8b75c350a8 100644 --- a/pgxn/hnsw/hnsw.control +++ b/pgxn/hnsw/hnsw.control @@ -1,4 +1,4 @@ -comment = 'hNsw index' +comment = 'hnsw index' default_version = '0.1.0' module_pathname = '$libdir/hnsw' relocatable = true