diff --git a/src/backend/commands/resgroupcmds.c b/src/backend/commands/resgroupcmds.c index fdf93564b4df79326a35a5b3c69a5a88097af507..9a4de023ac3bcda2f815311c711af32d97df1253 100644 --- a/src/backend/commands/resgroupcmds.c +++ b/src/backend/commands/resgroupcmds.c @@ -59,7 +59,7 @@ #define RESGROUP_MAX_MEMORY_SHARED_QUOTA (100) #define RESGROUP_MIN_MEMORY_SPILL_RATIO (0) -#define RESGROUP_MAX_MEMORY_SPILL_RATIO (100) +#define RESGROUP_MAX_MEMORY_SPILL_RATIO (INT_MAX) /* * The names must be in the same order as ResGroupMemAuditorType. diff --git a/src/backend/utils/misc/guc_gp.c b/src/backend/utils/misc/guc_gp.c index cd8a618445763b0a878a1c4aa2c4d9a6146b2b3d..654e8bbed156380757ee6e1e8a66b7850084c006 100644 --- a/src/backend/utils/misc/guc_gp.c +++ b/src/backend/utils/misc/guc_gp.c @@ -2974,7 +2974,7 @@ struct config_int ConfigureNamesInt_gp[] = NULL }, &memory_spill_ratio, - 20, 0, 100, NULL, NULL + 20, 0, INT_MAX, NULL, NULL }, { diff --git a/src/backend/utils/resgroup/resgroup.c b/src/backend/utils/resgroup/resgroup.c index 968a209a9ec35fc4357202b0b4e73f04e11a87f5..577e969d11b9f1586e9bcdf98fb8148e8634ba25 100644 --- a/src/backend/utils/resgroup/resgroup.c +++ b/src/backend/utils/resgroup/resgroup.c @@ -169,7 +169,7 @@ struct ResGroupData { Oid groupId; /* Id for this group */ ResGroupCaps caps; /* capabilities of this group */ - int nRunning; /* number of running trans */ + volatile int nRunning; /* number of running trans */ PROC_QUEUE waitProcs; /* list of PGPROC objects waiting on this group */ int totalExecuted; /* total number of executed trans */ int totalQueued; /* total number of queued trans */ @@ -191,15 +191,15 @@ struct ResGroupData int32 memQuotaGranted; /* memory chunks for quota part */ int32 memSharedGranted; /* memory chunks for shared part */ - int32 memQuotaUsed; /* memory chunks assigned to all the running slots */ + volatile int32 memQuotaUsed; /* memory chunks assigned to all the running slots */ /* * memory usage of this group, should always equal to the * sum of session memory(session_state->sessionVmem) that * belongs to this group */ - int32 memUsage; - int32 memSharedUsage; + volatile int32 memUsage; + volatile int32 memSharedUsage; /* * operation functions for resource group @@ -219,7 +219,9 @@ struct ResGroupControl bool loaded; int32 totalChunks; /* total memory chunks on this segment */ - int32 freeChunks; /* memory chunks not allocated to any group */ + volatile int32 freeChunks; /* memory chunks not allocated to any group, + will be used for the query which group share + memory is not enough*/ int32 chunkSizeInBits; @@ -279,9 +281,9 @@ static void groupReleaseMemQuota(ResGroupData *group, ResGroupSlotData *slot); static int32 groupIncMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks); -static void groupDecMemUsage(ResGroupData *group, - ResGroupSlotData *slot, - int32 chunks); +static int32 groupDecMemUsage(ResGroupData *group, + ResGroupSlotData *slot, + int32 chunks); static void initSlot(ResGroupSlotData *slot, ResGroupData *group, int32 slotMemQuota); static void selfAttachResGroup(ResGroupData *group, ResGroupSlotData *slot); @@ -954,24 +956,27 @@ ResGroupReserveMemory(int32 memoryChunks, int32 overuseChunks, bool *waiverUsed) overuseMem = groupIncMemUsage(group, slot, memoryChunks); /* then check whether there is over usage */ - if (CritSectionCount == 0 && overuseMem > overuseChunks) + if (CritSectionCount == 0) { - /* if the over usage is larger than allowed then revert the change */ - groupDecMemUsage(group, slot, memoryChunks); + if (overuseMem > overuseChunks) + { + /* if the over usage is larger than allowed then revert the change */ + groupDecMemUsage(group, slot, memoryChunks); - /* also revert in proc */ - self->memUsage -= memoryChunks; - Assert(self->memUsage >= 0); + /* also revert in proc */ + self->memUsage -= memoryChunks; + Assert(self->memUsage >= 0); - if (overuseChunks == 0) - ResGroupDumpMemoryInfo(); + if (overuseChunks == 0) + ResGroupDumpMemoryInfo(); - return false; - } - else if (CritSectionCount == 0 && overuseMem > 0) - { - /* the over usage is within the allowed threshold */ - *waiverUsed = true; + return false; + } + else if (overuseMem > 0) + { + /* the over usage is within the allowed threshold */ + *waiverUsed = true; + } } return true; @@ -1106,14 +1111,15 @@ bindGroupOperation(ResGroupData *group) /* * Add chunks into group and slot memory usage. * - * Return the over used chunks. + * Return the total over used chunks of global share */ static int32 groupIncMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks) { - int32 slotMemUsage; - int32 sharedMemUsage; - int32 overuseMem = 0; + int32 slotMemUsage; /* the memory current slot has been used */ + int32 sharedMemUsage; /* the total shared memory usage, + sum of group share and global share */ + int32 globalOveruse = 0; /* the total over used chunks of global share*/ /* Add the chunks to memUsage in slot */ slotMemUsage = pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &slot->memUsage, @@ -1123,30 +1129,40 @@ groupIncMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks) sharedMemUsage = slotMemUsage - slot->memQuota; if (sharedMemUsage > 0) { - int32 total; - /* Decide how many chunks should be counted as shared memory */ - sharedMemUsage = Min(sharedMemUsage, chunks); - - /* Add these chunks to memSharedUsage in group */ - total = pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &group->memSharedUsage, - sharedMemUsage); - - /* Calculate the over used chunks */ - overuseMem = Max(0, total - group->memSharedGranted); + int32 deltaSharedMemUsage = Min(sharedMemUsage, chunks); + + /* Add these chunks to memSharedUsage in group, + * and record the old value*/ + int32 oldSharedUsage = pg_atomic_fetch_add_u32((pg_atomic_uint32 *) + &group->memSharedUsage, + deltaSharedMemUsage); + /* the free space of group share */ + int32 oldSharedFree = Max(0, group->memSharedGranted - oldSharedUsage); + + /* Calculate the global over used chunks */ + int32 deltaGlobalSharedMemUsage = Max(0, deltaSharedMemUsage - oldSharedFree); + + /* freeChunks -= deltaGlobalSharedMemUsage and get the new value */ + int32 newFreeChunks = pg_atomic_sub_fetch_u32((pg_atomic_uint32 *) + &pResGroupControl->freeChunks, + deltaGlobalSharedMemUsage); + /* calculate the total over used chunks of global share */ + globalOveruse = Max(0, 0 - newFreeChunks); } /* Add the chunks to memUsage in group */ pg_atomic_add_fetch_u32((pg_atomic_uint32 *) &group->memUsage, chunks); - return overuseMem; + return globalOveruse; } /* - * Sub chunks from group and slot memory usage. + * Sub chunks from group ,slot memory usage and global shared memory. + * return memory chunks of global shared released this time */ -static void +static int32 groupDecMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks) { int32 value; @@ -1168,13 +1184,25 @@ groupDecMemUsage(ResGroupData *group, ResGroupSlotData *slot, int32 chunks) if (sharedMemUsage > 0) { /* Decide how many chunks should be counted as shared memory */ - sharedMemUsage = Min(sharedMemUsage, chunks); + int32 deltaSharedMemUsage = Min(sharedMemUsage, chunks); /* Sub chunks from memSharedUsage in group */ - value = pg_atomic_sub_fetch_u32((pg_atomic_uint32 *) &group->memSharedUsage, - sharedMemUsage); - Assert(value >= 0); + int32 oldSharedUsage = pg_atomic_fetch_sub_u32((pg_atomic_uint32 *) &group->memSharedUsage, + deltaSharedMemUsage); + Assert(oldSharedUsage >= deltaSharedMemUsage); + + /* record the total global share usage of current group */ + int32 grpTotalGlobalUsage = Max(0, oldSharedUsage - group->memSharedGranted); + /* calculate the global share usage of current release */ + int32 deltaGlobalSharedMemUsage = Min(grpTotalGlobalUsage, deltaSharedMemUsage); + /* add chunks to global shared memory */ + pg_atomic_add_fetch_u32((pg_atomic_uint32 *) + &pResGroupControl->freeChunks, + deltaGlobalSharedMemUsage); + return deltaGlobalSharedMemUsage; } + + return 0; } /* @@ -1593,18 +1621,34 @@ groupApplyMemCaps(ResGroupData *group) static int32 mempoolReserve(Oid groupId, int32 chunks) { + int32 oldFreeChunks; + int32 newFreeChunks; + int32 reserved = 0; + Assert(LWLockHeldExclusiveByMe(ResGroupLock)); - LOG_RESGROUP_DEBUG(LOG, "allocate %u out of %u chunks to group %d", - chunks, pResGroupControl->freeChunks, groupId); + /* Compare And Save to avoid concurrency problem without using lock */ + while (true) + { + oldFreeChunks = pg_atomic_read_u32((pg_atomic_uint32 *) + &pResGroupControl->freeChunks); + reserved = Min(Max(0, oldFreeChunks), chunks); + newFreeChunks = oldFreeChunks - reserved; + if (reserved == 0) + break; + if (pg_atomic_compare_exchange_u32((pg_atomic_uint32 *) + &pResGroupControl->freeChunks, + (uint32 *) &oldFreeChunks, + (uint32) newFreeChunks)) + break; + } - chunks = Min(pResGroupControl->freeChunks, chunks); - pResGroupControl->freeChunks -= chunks; + LOG_RESGROUP_DEBUG(LOG, "allocate %u out of %u chunks to group %d", + reserved, oldFreeChunks, groupId); - Assert(pResGroupControl->freeChunks >= 0); - Assert(pResGroupControl->freeChunks <= pResGroupControl->totalChunks); + Assert(newFreeChunks <= pResGroupControl->totalChunks); - return chunks; + return reserved; } /* @@ -1613,16 +1657,19 @@ mempoolReserve(Oid groupId, int32 chunks) static void mempoolRelease(Oid groupId, int32 chunks) { - LOG_RESGROUP_DEBUG(LOG, "free %u to pool(%u) chunks from group %d", - chunks, pResGroupControl->freeChunks, groupId); + int32 newFreeChunks; Assert(LWLockHeldExclusiveByMe(ResGroupLock)); Assert(chunks >= 0); - pResGroupControl->freeChunks += chunks; + newFreeChunks = pg_atomic_add_fetch_u32((pg_atomic_uint32 *) + &pResGroupControl->freeChunks, + chunks); + + LOG_RESGROUP_DEBUG(LOG, "free %u to pool(%u) chunks from group %d", + chunks, newFreeChunks - chunks, groupId); - Assert(pResGroupControl->freeChunks >= 0); - Assert(pResGroupControl->freeChunks <= pResGroupControl->totalChunks); + Assert(newFreeChunks <= pResGroupControl->totalChunks); } /* diff --git a/src/test/isolation2/expected/resgroup/resgroup_alter_memory_spill_ratio.out b/src/test/isolation2/expected/resgroup/resgroup_alter_memory_spill_ratio.out index 29d413094a5738b57a91c316f6599ea069912675..86b5c3943d7fccbcfc5c9ffbf009b46fbe396272 100644 --- a/src/test/isolation2/expected/resgroup/resgroup_alter_memory_spill_ratio.out +++ b/src/test/isolation2/expected/resgroup/resgroup_alter_memory_spill_ratio.out @@ -25,7 +25,7 @@ groupname |memory_shared_quota|proposed_memory_shared_quota|memory_spill_rati rg_spill_test|20 |20 |20 |20 (1 row) --- positive, memory_spill_ratio range is [0, 100] +-- positive, memory_spill_ratio range is [0, 2147483647] ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 0; ALTER SELECT * FROM rg_spill_status; @@ -58,9 +58,9 @@ groupname |memory_shared_quota|proposed_memory_shared_quota|memory_spill_rati rg_spill_test|20 |20 |81 |81 (1 row) --- negative: memory_spill_ratio is larger than RESGROUP_MAX_MEMORY_SPILL_RATIO -ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 101; -ERROR: memory_spill_ratio range is [0, 100] +-- negative: memory_spill_ratio is negative +ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO -1; +ERROR: memory_spill_ratio range is [0, 2147483647] SELECT * FROM rg_spill_status; groupname |memory_shared_quota|proposed_memory_shared_quota|memory_spill_ratio|proposed_memory_spill_ratio -------------+-------------------+----------------------------+------------------+--------------------------- diff --git a/src/test/isolation2/expected/resgroup/resgroup_set_memory_spill_ratio.out b/src/test/isolation2/expected/resgroup/resgroup_set_memory_spill_ratio.out index c22bfe742c1dd2f60b8bcaddc993ec59eaa4ef2a..800494a1c1a36c711451a46dad45ee2dc6f289d4 100644 --- a/src/test/isolation2/expected/resgroup/resgroup_set_memory_spill_ratio.out +++ b/src/test/isolation2/expected/resgroup/resgroup_set_memory_spill_ratio.out @@ -63,8 +63,8 @@ SELECT 1; (1 row) -- negative set to session level -SET MEMORY_SPILL_RATIO TO 101; -ERROR: 101 is outside the valid range for parameter "memory_spill_ratio" (0 .. 100) +SET MEMORY_SPILL_RATIO TO -1; +ERROR: -1 is outside the valid range for parameter "memory_spill_ratio" (0 .. 2147483647) SHOW MEMORY_SPILL_RATIO; memory_spill_ratio ------------------ diff --git a/src/test/isolation2/expected/resgroup/resgroup_syntax.out b/src/test/isolation2/expected/resgroup/resgroup_syntax.out index d93efbb357ccedb27ebe7e3e768d6e4ac7164140..26f934eee4a66bdb6e4aaf2d8f18a0b8d6b3b7c9 100644 --- a/src/test/isolation2/expected/resgroup/resgroup_syntax.out +++ b/src/test/isolation2/expected/resgroup/resgroup_syntax.out @@ -176,7 +176,7 @@ ERROR: memory_auditor should be "vmtracker" or "cgroup" CREATE RESOURCE GROUP rg_test_group WITH (concurrency=1, cpu_rate_limit=10, memory_limit=10, memory_auditor="cgroup"); ERROR: resource group concurrency must be 0 when group memory_auditor is cgroup --- memory_spill_ratio range is [0, 100] +-- memory_spill_ratio range is [0, 2147483647] -- no limit on the sum of memory_shared_quota and memory_spill_ratio CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=10, memory_spill_ratio=0); CREATE @@ -187,7 +187,7 @@ CREATE DROP RESOURCE GROUP rg_test_group; DROP CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=10, memory_spill_ratio=-1); -ERROR: memory_spill_ratio range is [0, 100] +ERROR: memory_spill_ratio range is [0, 2147483647] CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=-1, memory_spill_ratio=10); ERROR: memory_shared_quota range is [0, 100] @@ -251,7 +251,7 @@ CREATE DROP RESOURCE GROUP rg_test_group; DROP --- memory_spill_ratio range is [0, 100] +-- memory_spill_ratio range is [0, 2147483647] -- no limit on the sum of memory_shared_quota and memory_spill_ratio CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=0, memory_spill_ratio=1); CREATE diff --git a/src/test/isolation2/expected/resgroup/resgroup_unlimit_memory_spill_ratio.out b/src/test/isolation2/expected/resgroup/resgroup_unlimit_memory_spill_ratio.out index be374cf5fd7037d88a154084ad4363494d76619d..5b1332d8acc49833dfd6850f385d1cf1b9b99b6a 100644 --- a/src/test/isolation2/expected/resgroup/resgroup_unlimit_memory_spill_ratio.out +++ b/src/test/isolation2/expected/resgroup/resgroup_unlimit_memory_spill_ratio.out @@ -20,12 +20,7 @@ DROP RESOURCE GROUP rg_spill_test; DROP CREATE RESOURCE GROUP rg_spill_test WITH (concurrency=10, cpu_rate_limit=20, memory_limit=20, memory_shared_quota=50, memory_spill_ratio=-1); -ERROR: memory_spill_ratio range is [0, 100] -DROP RESOURCE GROUP rg_spill_test; -ERROR: resource group "rg_spill_test" does not exist - -CREATE RESOURCE GROUP rg_spill_test WITH (concurrency=10, cpu_rate_limit=20, memory_limit=20, memory_shared_quota=50, memory_spill_ratio=101); -ERROR: memory_spill_ratio range is [0, 100] +ERROR: memory_spill_ratio range is [0, 2147483647] DROP RESOURCE GROUP rg_spill_test; ERROR: resource group "rg_spill_test" does not exist @@ -40,9 +35,9 @@ ALTER ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 100; ALTER ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO -1; -ERROR: memory_spill_ratio range is [0, 100] -ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 101; -ERROR: memory_spill_ratio range is [0, 100] +ERROR: memory_spill_ratio range is [0, 2147483647] +ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 10000; +ALTER DROP RESOURCE GROUP rg_spill_test; DROP @@ -91,7 +86,7 @@ SELECT 1; (1 row) SET MEMORY_SPILL_RATIO TO -1; -ERROR: -1 is outside the valid range for parameter "memory_spill_ratio" (0 .. 100) +ERROR: -1 is outside the valid range for parameter "memory_spill_ratio" (0 .. 2147483647) SHOW MEMORY_SPILL_RATIO; memory_spill_ratio ------------------ @@ -103,12 +98,12 @@ SELECT 1; 1 (1 row) -SET MEMORY_SPILL_RATIO TO 101; -ERROR: 101 is outside the valid range for parameter "memory_spill_ratio" (0 .. 100) +SET MEMORY_SPILL_RATIO TO 10000; +SET SHOW MEMORY_SPILL_RATIO; memory_spill_ratio ------------------ -100 +10000 (1 row) SELECT 1; ?column? diff --git a/src/test/isolation2/input/resgroup/resgroup_memory_limit.source b/src/test/isolation2/input/resgroup/resgroup_memory_limit.source index 0b6d1d99a401d0431603b26e1640f74d92bade55..23cf4625227d015e949db62da965c3cba3d5fe28 100644 --- a/src/test/isolation2/input/resgroup/resgroup_memory_limit.source +++ b/src/test/isolation2/input/resgroup/resgroup_memory_limit.source @@ -1,180 +1,506 @@ -- start_ignore DROP ROLE IF EXISTS role1_memory_test; DROP RESOURCE GROUP rg1_memory_test; +DROP RESOURCE GROUP rg2_memory_test; -- end_ignore CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; -CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ - SELECT * FROM resGroupPalloc($2) +CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ + SELECT * FROM resGroupPalloc($1) $$ LANGUAGE sql; --- --- first create the resgroup with memory_shared_quota == 0. --- so each resgroup slot gets a fixed memory quota of 0.5. --- - +CREATE OR REPLACE VIEW rg_mem_status AS + SELECT groupname, memory_limit, proposed_memory_limit, + memory_shared_quota, proposed_memory_shared_quota + FROM gp_toolkit.gp_resgroup_config + WHERE groupname='rg1_memory_test' OR groupname='rg2_memory_test' + ORDER BY groupid; + +CREATE OR REPLACE VIEW memory_result AS SELECT rsgname, memory_usage from gp_toolkit.gp_resgroup_status; + +-- 1) single allocation +-- Group Share Quota = 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52% => 52% +-- rg1's slot quota: 52% / 2 * 2 => 52% +-- rg1's single slot quota: 52% / 2 => 26% +-- rg1's shared quota: %52 - %52 => %0 +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 52%/2 + 0% + 8% => 34% CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, - memory_limit=50, memory_shared_quota=0); + memory_limit=52, memory_shared_quota=0); CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; --- 1) on QD only with memory_shared_quota == 0 - +-- 1a) on QD 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); +1: SELECT hold_memory_by_percent(0.14 / 0.52); +1: SELECT hold_memory_by_percent(0.14 / 0.52); 1q: 1: SET ROLE TO role1_memory_test; 1: BEGIN; -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); +1: SELECT hold_memory_by_percent(0.14 / 0.52); +1: SELECT hold_memory_by_percent(0.14 / 0.52); 1q: 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.45); -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT hold_memory_by_percent(0.42 / 0.52); 1q: +-- 1b) on QEs 1: SET ROLE TO role1_memory_test; -1: BEGIN; -1: SELECT hold_memory_by_percent(1,0.45); -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; 1q: 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.55); +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.42 / 0.52)=0; 1q: --- 2) on QEs with memory_shared_quota == 0 +DROP ROLE role1_memory_test; +DROP RESOURCE GROUP rg1_memory_test; + +-- 2) single allocation +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% * 60 /100 => 31% +-- rg1's single slot quota: 31% / 2 => 15.5% +-- rg1's shared quota: 52% - 31% => 21% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 15.5% + 21% + 8% => 44.5% + +CREATE RESOURCE GROUP rg1_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=52, memory_shared_quota=40); +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; + +-- 2a) on QD +1: SET ROLE TO role1_memory_test; +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1q: 1: SET ROLE TO role1_memory_test; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: BEGIN; +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +1: SELECT hold_memory_by_percent(0.12 / 0.52); 1q: 1: SET ROLE TO role1_memory_test; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.45)=0; +1: SELECT hold_memory_by_percent(0.48 / 0.52); 1q: +-- 2b) on QEs 1: SET ROLE TO role1_memory_test; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.55)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; 1q: --- --- now recreate the resgroup with memory_shared_quota > 0. --- so each resgroup slot gets a fixed memory quota of 0.3, --- there is also a shared memory pool of 0.4, so the actual --- memory usage in each slot can be 0.3~0.7. --- +1: SET ROLE TO role1_memory_test; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.48 / 0.52)=0; +1q: DROP ROLE role1_memory_test; DROP RESOURCE GROUP rg1_memory_test; + +-- 3) single allocation +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota = 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 0 +-- rg1's shared quota: 52% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 52% + 8% => 60% + CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, - memory_limit=10, memory_shared_quota=40); + memory_limit=52, memory_shared_quota=100); CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; --- 3) on QD with memory_shared_quota > 0 - +-- 3a) on QD 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.65); +1: SELECT hold_memory_by_percent(0.25 / 0.52); +1: SELECT hold_memory_by_percent(0.25 / 0.52); +1: SELECT hold_memory_by_percent(0.25 / 0.52); 1q: 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.75); +1: BEGIN; +1: SELECT hold_memory_by_percent(0.25 / 0.52); +1: SELECT hold_memory_by_percent(0.25 / 0.52); +1: SELECT hold_memory_by_percent(0.25 / 0.52); 1q: 1: SET ROLE TO role1_memory_test; -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.75 / 0.52); 1q: --- 4) on QEs with memory_shared_quota > 0 +-- 3b) on QEs +1: SET ROLE TO role1_memory_test; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +1q: 1: SET ROLE TO role1_memory_test; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.75 / 0.52)=0; 1q: --- 5) QD: concurrent transactions in same group with memory_shared_quota > 0 +DROP ROLE role1_memory_test; +DROP RESOURCE GROUP rg1_memory_test; + +-- 4) multi allocation in one group +-- Group Share Quota = 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% / 2 * 2 => 52% +-- rg1's single slot quota: 52% / 2 => 26% +-- rg1's shared quota: 0 +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 26% + 8% => 34% + +CREATE RESOURCE GROUP rg1_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=52, memory_shared_quota=0); +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +-- 4a) on QD +-- not exceed the global share 1: SET ROLE TO role1_memory_test; -1: BEGIN; -1: SELECT hold_memory_by_percent(1,0.6); 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT hold_memory_by_percent(1,0.3); +1: SELECT hold_memory_by_percent(0.28 / 0.52); +2: SELECT hold_memory_by_percent(0.28 / 0.52); +1q: 2q: + +-- exceed the global share +1: SET ROLE TO role1_memory_test; 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT hold_memory_by_percent(1,0.3); -2: SELECT hold_memory_by_percent(1,0.2); -2q: +1: SELECT hold_memory_by_percent(0.32 / 0.52); +2: SELECT hold_memory_by_percent(0.32 / 0.52); 1q: +2q: --- 6) QE: concurrent transactions in same group with memory_shared_quota > 0 +-- allocate serially +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.32 / 0.52); +1q: +SELECT pg_sleep(1); +2: SELECT hold_memory_by_percent(0.32 / 0.52); +2q: +-- 4b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; 1: BEGIN; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.6)=0; +2: BEGIN; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.28 / 0.52)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.28 / 0.52)=0; +1q: +2q: + +-- exceed the global share +1: SET ROLE TO role1_memory_test; 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +1q: 2q: + +-- allocate serially +1: SET ROLE TO role1_memory_test; 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +1q: +SELECT pg_sleep(1); +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; 2q: + +DROP ROLE role1_memory_test; +DROP RESOURCE GROUP rg1_memory_test; + +-- 5) multi allocation in one group +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% * 50 / 100 => 26% +-- rg1's single slot quota: 26% / 2 => 13% +-- rg1's shared quota: 52% - 13% * 2 => 26% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 13% + 26% + 8% => 47% + +CREATE RESOURCE GROUP rg1_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=52, memory_shared_quota=50); +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; + +-- 5a) on QD +-- not exceed the global share +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; +1: BEGIN; +2: BEGIN; +-- reserve all the group shared quota +1: SELECT hold_memory_by_percent(0.39 / 0.52); +-- must allocate from global share +2: SELECT hold_memory_by_percent(0.2 / 0.52); 1q: +2q: --- 7) QD: concurrent transactions in same group with memory_shared_quota = 100 +-- exceed the global share +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.39 / 0.52); +2: SELECT hold_memory_by_percent(0.39 / 0.52); +1q: +2q: -ALTER RESOURCE GROUP rg1_memory_test SET memory_shared_quota 100; +-- allocate serially +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.39 / 0.52); +1q: +SELECT pg_sleep(1); +2: SELECT hold_memory_by_percent(0.39 / 0.52); +2q: +-- 5b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role1_memory_test; 1: BEGIN; -1: SELECT hold_memory_by_percent(1,0.6); +2: BEGIN; +-- reserve all the group shared quota +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +-- must allocate from global share +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.52)=0; +1q: +2q: + +-- exceed the global share +1: SET ROLE TO role1_memory_test; 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT hold_memory_by_percent(1,0.3); +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +1q: 2q: + +-- allocate serially +1: SET ROLE TO role1_memory_test; 2: SET ROLE TO role1_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT hold_memory_by_percent(1,0.3); -2: SELECT hold_memory_by_percent(1,0.2); +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +1q: +SELECT pg_sleep(1); +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; 2q: + +DROP ROLE role1_memory_test; +DROP RESOURCE GROUP rg1_memory_test; + +-- 6) multi allocation in different group +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 20 / 100 => 20% +-- rg1's slot quota: 20% * 60 / 100 / 2 * 2 => 12% +-- rg1's single slot quota: 12% / 2 => 6% +-- rg1's shared quota: 20% - 6% * 2 => 8% +-- rg2 same as rg1 +-- system free chunks: 100% - 10% - 30% - 100%*20/100 - 100%*20/100 => 20% +-- memory available to one slot in rg1/rg2: 6% + 8% + 20% => 34% + +CREATE RESOURCE GROUP rg1_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=20, memory_shared_quota=40); +CREATE RESOURCE GROUP rg2_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=20, memory_shared_quota=40); +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE ROLE role2_memory_test RESOURCE GROUP rg2_memory_test; + +-- 6a) on QD +-- not exceed the global share +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.2 / 0.2); +2: SELECT hold_memory_by_percent(0.2 / 0.2); 1q: +2q: --- 8) QE: concurrent transactions in same group with memory_shared_quota = 100 +-- exceed the global share +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.3 / 0.2); +2: SELECT hold_memory_by_percent(0.3 / 0.2); +1q: +2q: -ALTER RESOURCE GROUP rg1_memory_test SET memory_shared_quota 100; +-- allocate serially +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT hold_memory_by_percent(0.3 / 0.2); +1q: +SELECT pg_sleep(1); +2: SELECT hold_memory_by_percent(0.3 / 0.2); +2q: +-- 6b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; 1: BEGIN; -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.6)=0; -2: SET ROLE TO role1_memory_test; 2: BEGIN; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.2)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.2)=0; +1q: 2q: -2: SET ROLE TO role1_memory_test; + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; +1: BEGIN; 2: BEGIN; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; +1q: 2q: + +-- allocate serially +1: SET ROLE TO role1_memory_test; +2: SET ROLE TO role2_memory_test; +1: BEGIN; +2: BEGIN; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; 1q: +SELECT pg_sleep(1); +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; +2q: --- cleanup DROP ROLE role1_memory_test; +DROP ROLE role2_memory_test; DROP RESOURCE GROUP rg1_memory_test; +DROP RESOURCE GROUP rg2_memory_test; + +-- 7) DBA can increase global shared memory by decreasing +-- any existing group_memory_limit +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 30 / 100 => 30% +-- rg1's slot quota: 30% +-- rg1's single slot quota: 30% / 2 => 15% +-- rg1's shared quota: 0 +-- rg2 same as rg1 +-- system free chunks: 100% - 10% - 30% - 30% - 30% => 0 +-- memory available to one slot in rg1/rg2: 15% + 0 + 0 => 15% + +CREATE RESOURCE GROUP rg1_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=30, memory_shared_quota=0); +CREATE RESOURCE GROUP rg2_memory_test + WITH (concurrency=2, cpu_rate_limit=10, + memory_limit=30, memory_shared_quota=0); +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE ROLE role2_memory_test RESOURCE GROUP rg2_memory_test; + +-- 7a) on QD +-- not enough memory +1: SET ROLE TO role1_memory_test; +1: SELECT hold_memory_by_percent(0.2 / 0.3); +1q: + +-- alter rg2 memory_limit so last query has enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 20; +-- system free chunks: 100% - 10% - 30% - 30% - 20% => 10% +-- memory available to one slot in rg1/rg2: 15% + 0 + 10% => 25% + +-- enough memory for allocating +1: SET ROLE TO role1_memory_test; +1: SELECT hold_memory_by_percent(0.2 / 0.3); +1q: + +-- 7b) on QEs +-- not enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 30; +1: SET ROLE TO role1_memory_test; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.3)=0; +1q: + +-- alter rg2 memory_limit so last query has enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 20; +-- system free chunks: 100% - 10% - 30% - 30% - 20% => 10% +-- memory available to one slot in rg1/rg2: 15% + 0 + 10% => 25% + +-- enough memory for allocating +1: SET ROLE TO role1_memory_test; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.3)=0; +1q: + +DROP ROLE role1_memory_test; +DROP ROLE role2_memory_test; +DROP RESOURCE GROUP rg1_memory_test; +DROP RESOURCE GROUP rg2_memory_test; + diff --git a/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source b/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source index dfc1752830cbf24080ff5db3a33171619ec22deb..0d7ba431603a02ab64842cef7ddeebb3ee1d022b 100644 --- a/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source +++ b/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source @@ -152,3 +152,4 @@ DROP ROLE role1_memory_test; DROP ROLE role2_memory_test; DROP RESOURCE GROUP rg1_memory_test; DROP RESOURCE GROUP rg2_memory_test; +DROP VIEW memory_result; diff --git a/src/test/isolation2/output/resgroup/resgroup_memory_limit.source b/src/test/isolation2/output/resgroup/resgroup_memory_limit.source index b71dd36519a07d3bda98f52b2db16428cb658216..b2858d8139448f8317e4041da02cdef238e82e6f 100644 --- a/src/test/isolation2/output/resgroup/resgroup_memory_limit.source +++ b/src/test/isolation2/output/resgroup/resgroup_memory_limit.source @@ -3,39 +3,54 @@ DROP ROLE IF EXISTS role1_memory_test; DROP DROP RESOURCE GROUP rg1_memory_test; ERROR: resource group "rg1_memory_test" does not exist +DROP RESOURCE GROUP rg2_memory_test; +ERROR: resource group "rg2_memory_test" does not exist -- end_ignore CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE -CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($2) $$ LANGUAGE sql; +CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($1) $$ LANGUAGE sql; CREATE --- --- first create the resgroup with memory_shared_quota == 0. --- so each resgroup slot gets a fixed memory quota of 0.5. --- +CREATE OR REPLACE VIEW rg_mem_status AS SELECT groupname, memory_limit, proposed_memory_limit, memory_shared_quota, proposed_memory_shared_quota FROM gp_toolkit.gp_resgroup_config WHERE groupname='rg1_memory_test' OR groupname='rg2_memory_test' ORDER BY groupid; +CREATE + +CREATE OR REPLACE VIEW memory_result AS SELECT rsgname, memory_usage from gp_toolkit.gp_resgroup_status; +CREATE -CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=50, memory_shared_quota=0); +-- 1) single allocation +-- Group Share Quota = 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52% => 52% +-- rg1's slot quota: 52% / 2 * 2 => 52% +-- rg1's single slot quota: 52% / 2 => 26% +-- rg1's shared quota: %52 - %52 => %0 +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 52%/2 + 0% + 8% => 34% +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=52, memory_shared_quota=0); CREATE CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; CREATE --- 1) on QD only with memory_shared_quota == 0 - +-- 1a) on QD 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 @@ -45,17 +60,17 @@ CONTEXT: SQL function "hold_memory_by_percent" statement 1 SET 1: BEGIN; BEGIN -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT hold_memory_by_percent(0.14 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 @@ -63,12 +78,82 @@ CONTEXT: SQL function "hold_memory_by_percent" statement 1 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT hold_memory_by_percent(0.42 / 0.52); +ERROR: Out of memory +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +-- 1b) on QEs +1: SET ROLE TO role1_memory_test; +SET +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; +count +----- +0 +(1 row) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; +count +----- +0 +(1 row) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.14 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=18610) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +1: SET ROLE TO role1_memory_test; +SET +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.42 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=18619) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +DROP ROLE role1_memory_test; +DROP +DROP RESOURCE GROUP rg1_memory_test; +DROP + +-- 2) single allocation +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% * 60 /100 => 31% +-- rg1's single slot quota: 31% / 2 => 15.5% +-- rg1's shared quota: 52% - 31% => 21% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 15.5% + 21% + 8% => 44.5% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=52, memory_shared_quota=40); +CREATE +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE + +-- 2a) on QD +1: SET ROLE TO role1_memory_test; +SET +1: SELECT hold_memory_by_percent(0.12 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.12 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.12 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 @@ -78,12 +163,22 @@ CONTEXT: SQL function "hold_memory_by_percent" statement 1 SET 1: BEGIN; BEGIN -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.12 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.45); +1: SELECT hold_memory_by_percent(0.12 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.12 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 @@ -91,288 +186,739 @@ CONTEXT: SQL function "hold_memory_by_percent" statement 1 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.55); +1: SELECT hold_memory_by_percent(0.48 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... --- 2) on QEs with memory_shared_quota == 0 - +-- 2b) on QEs 1: SET ROLE TO role1_memory_test; SET -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; count ----- 0 (1 row) -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; count ----- 0 (1 row) -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -ERROR: Out of memory (seg0 slice1 172.17.0.3:25432 pid=158454) -DETAIL: Resource group memory limit reached -CONTEXT: SQL function "hold_memory_by_percent" statement 1 -1q: ... - -1: SET ROLE TO role1_memory_test; -SET -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.45)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; count ----- 0 (1 row) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.12 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=19259) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... 1: SET ROLE TO role1_memory_test; SET -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.55)=0; -ERROR: Out of memory (seg0 slice1 172.17.0.3:25432 pid=158468) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.48 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=19269) DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... --- --- now recreate the resgroup with memory_shared_quota > 0. --- so each resgroup slot gets a fixed memory quota of 0.3, --- there is also a shared memory pool of 0.4, so the actual --- memory usage in each slot can be 0.3~0.7. --- - DROP ROLE role1_memory_test; DROP DROP RESOURCE GROUP rg1_memory_test; DROP -CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=10, memory_shared_quota=40); + +-- 3) single allocation +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota = 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 0 +-- rg1's shared quota: 52% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 52% + 8% => 60% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=52, memory_shared_quota=100); CREATE CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; CREATE --- 3) on QD with memory_shared_quota > 0 +-- 3a) on QD +1: SET ROLE TO role1_memory_test; +SET +1: SELECT hold_memory_by_percent(0.25 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.25 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.25 / 0.52); +ERROR: Out of memory +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.65); +1: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.25 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) +1: SELECT hold_memory_by_percent(0.25 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1: SELECT hold_memory_by_percent(0.25 / 0.52); +ERROR: Out of memory +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.75); +1: SELECT hold_memory_by_percent(0.75 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... +-- 3b) on QEs 1: SET ROLE TO role1_memory_test; SET -1: SELECT hold_memory_by_percent(1,0.2); +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +count +----- +0 +(1 row) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +count +----- +0 +(1 row) +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.25 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=19875) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +1: SET ROLE TO role1_memory_test; +SET +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.75 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=19884) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +DROP ROLE role1_memory_test; +DROP +DROP RESOURCE GROUP rg1_memory_test; +DROP + +-- 4) multi allocation in one group +-- Group Share Quota = 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% / 2 * 2 => 52% +-- rg1's single slot quota: 52% / 2 => 26% +-- rg1's shared quota: 0 +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 26% + 8% => 34% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=52, memory_shared_quota=0); +CREATE +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE + +-- 4a) on QD +-- not exceed the global share +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.28 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +2: SELECT hold_memory_by_percent(0.28 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +1q: ... +2q: ... + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.32 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -1: SELECT hold_memory_by_percent(1,0.2); +2: SELECT hold_memory_by_percent(0.32 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... +2q: ... --- 4) on QEs with memory_shared_quota > 0 +-- allocate serially +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.32 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT hold_memory_by_percent(0.32 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +2q: ... +-- 4b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; SET -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.28 / 0.52)=0; count ----- 0 (1 row) -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.28 / 0.52)=0; count ----- 0 (1 row) -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; +1q: ... +2q: ... + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; count ----- 0 (1 row) -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -ERROR: Out of memory (seg0 slice1 172.17.0.3:25432 pid=158496) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=21102) DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 1q: ... +2q: ... --- 5) QD: concurrent transactions in same group with memory_shared_quota > 0 - +-- allocate serially 1: SET ROLE TO role1_memory_test; SET +2: SET ROLE TO role1_memory_test; +SET 1: BEGIN; BEGIN -1: SELECT hold_memory_by_percent(1,0.6); -hold_memory_by_percent ----------------------- -0 +2: BEGIN; +BEGIN +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +count +----- +0 (1 row) +1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.32 / 0.52)=0; +count +----- +0 +(1 row) +2q: ... + +DROP ROLE role1_memory_test; +DROP +DROP RESOURCE GROUP rg1_memory_test; +DROP + +-- 5) multi allocation in one group +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 52 / 100 => 52% +-- rg1's slot quota: 52% * 50 / 100 => 26% +-- rg1's single slot quota: 26% / 2 => 13% +-- rg1's shared quota: 52% - 13% * 2 => 26% +-- system free chunks: 100% - 10% - 30% - 52% => 8% +-- memory available to one slot in rg1: 13% + 26% + 8% => 47% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=52, memory_shared_quota=50); +CREATE +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE + +-- 5a) on QD +-- not exceed the global share +1: SET ROLE TO role1_memory_test; +SET 2: SET ROLE TO role1_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT hold_memory_by_percent(1,0.3); +-- reserve all the group shared quota +1: SELECT hold_memory_by_percent(0.39 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +-- must allocate from global share +2: SELECT hold_memory_by_percent(0.2 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) +1q: ... 2q: ... + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET 2: SET ROLE TO role1_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT hold_memory_by_percent(1,0.3); +1: SELECT hold_memory_by_percent(0.39 / 0.52); hold_memory_by_percent ---------------------- 0 (1 row) -2: SELECT hold_memory_by_percent(1,0.2); +2: SELECT hold_memory_by_percent(0.39 / 0.52); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 -2q: ... 1q: ... +2q: ... --- 6) QE: concurrent transactions in same group with memory_shared_quota > 0 +-- allocate serially +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role1_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.39 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT hold_memory_by_percent(0.39 / 0.52); +hold_memory_by_percent +---------------------- +0 +(1 row) +2q: ... +-- 5b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; SET +2: SET ROLE TO role1_memory_test; +SET 1: BEGIN; BEGIN -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.6)=0; +2: BEGIN; +BEGIN +-- reserve all the group shared quota +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; count ----- 0 (1 row) +-- must allocate from global share +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.52)=0; +count +----- +0 +(1 row) +1q: ... +2q: ... + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET 2: SET ROLE TO role1_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; count ----- 0 (1 row) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=21783) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... 2q: ... + +-- allocate serially +1: SET ROLE TO role1_memory_test; +SET 2: SET ROLE TO role1_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; count ----- 0 (1 row) -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -ERROR: Out of memory (seg0 slice1 172.17.0.3:25432 pid=158538) -DETAIL: Resource group memory limit reached -CONTEXT: SQL function "hold_memory_by_percent" statement 1 -2q: ... 1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.39 / 0.52)=0; +count +----- +0 +(1 row) +2q: ... --- 7) QD: concurrent transactions in same group with memory_shared_quota = 100 +DROP ROLE role1_memory_test; +DROP +DROP RESOURCE GROUP rg1_memory_test; +DROP -ALTER RESOURCE GROUP rg1_memory_test SET memory_shared_quota 100; -ALTER +-- 6) multi allocation in different group +-- Group Share Quota > 0 +-- Global Share Quota > 0 +-- Slot Quota > 0 +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 20 / 100 => 20% +-- rg1's slot quota: 20% * 60 / 100 / 2 * 2 => 12% +-- rg1's single slot quota: 12% / 2 => 6% +-- rg1's shared quota: 20% - 6% * 2 => 8% +-- rg2 same as rg1 +-- system free chunks: 100% - 10% - 30% - 100%*20/100 - 100%*20/100 => 20% +-- memory available to one slot in rg1/rg2: 6% + 8% + 20% => 34% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=20, memory_shared_quota=40); +CREATE +CREATE RESOURCE GROUP rg2_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=20, memory_shared_quota=40); +CREATE +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE +CREATE ROLE role2_memory_test RESOURCE GROUP rg2_memory_test; +CREATE +-- 6a) on QD +-- not exceed the global share 1: SET ROLE TO role1_memory_test; SET +2: SET ROLE TO role2_memory_test; +SET 1: BEGIN; BEGIN -1: SELECT hold_memory_by_percent(1,0.6); +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.2 / 0.2); hold_memory_by_percent ---------------------- 0 (1 row) -2: SET ROLE TO role1_memory_test; -SET -2: BEGIN; -BEGIN -2: SELECT hold_memory_by_percent(1,0.3); +2: SELECT hold_memory_by_percent(0.2 / 0.2); hold_memory_by_percent ---------------------- 0 (1 row) +1q: ... 2q: ... -2: SET ROLE TO role1_memory_test; + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role2_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT hold_memory_by_percent(1,0.3); +1: SELECT hold_memory_by_percent(0.3 / 0.2); hold_memory_by_percent ---------------------- 0 (1 row) -2: SELECT hold_memory_by_percent(1,0.2); +2: SELECT hold_memory_by_percent(0.3 / 0.2); ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 -2q: ... 1q: ... +2q: ... --- 8) QE: concurrent transactions in same group with memory_shared_quota = 100 - -ALTER RESOURCE GROUP rg1_memory_test SET memory_shared_quota 100; -ALTER +-- allocate serially +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role2_memory_test; +SET +1: BEGIN; +BEGIN +2: BEGIN; +BEGIN +1: SELECT hold_memory_by_percent(0.3 / 0.2); +hold_memory_by_percent +---------------------- +0 +(1 row) +1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT hold_memory_by_percent(0.3 / 0.2); +hold_memory_by_percent +---------------------- +0 +(1 row) +2q: ... +-- 6b) on QEs +-- not exceed the global share 1: SET ROLE TO role1_memory_test; SET +2: SET ROLE TO role2_memory_test; +SET 1: BEGIN; BEGIN -1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.6)=0; +2: BEGIN; +BEGIN +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.2)=0; count ----- 0 (1 row) -2: SET ROLE TO role1_memory_test; +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.2)=0; +count +----- +0 +(1 row) +1q: ... +2q: ... + +-- exceed the global share +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role2_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; count ----- 0 (1 row) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=22464) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... 2q: ... -2: SET ROLE TO role1_memory_test; + +-- allocate serially +1: SET ROLE TO role1_memory_test; +SET +2: SET ROLE TO role2_memory_test; SET +1: BEGIN; +BEGIN 2: BEGIN; BEGIN -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.3)=0; +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; +count +----- +0 +(1 row) +1q: ... +SELECT pg_sleep(1); +pg_sleep +-------- + +(1 row) +2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.3 / 0.2)=0; count ----- 0 (1 row) -2: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(t1.dbid,0.2)=0; -ERROR: Out of memory (seg0 slice1 192.168.99.102:25432 pid=18476) +2q: ... + +DROP ROLE role1_memory_test; +DROP +DROP ROLE role2_memory_test; +DROP +DROP RESOURCE GROUP rg1_memory_test; +DROP +DROP RESOURCE GROUP rg2_memory_test; +DROP + +-- 7) DBA can increase global shared memory by decreasing +-- any existing group_memory_limit +-- ----------------------- + +-- we assume system total chunks is 100% +-- rg1's expected: 100% * 30 / 100 => 30% +-- rg1's slot quota: 30% +-- rg1's single slot quota: 30% / 2 => 15% +-- rg1's shared quota: 0 +-- rg2 same as rg1 +-- system free chunks: 100% - 10% - 30% - 30% - 30% => 0 +-- memory available to one slot in rg1/rg2: 15% + 0 + 0 => 15% + +CREATE RESOURCE GROUP rg1_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=30, memory_shared_quota=0); +CREATE +CREATE RESOURCE GROUP rg2_memory_test WITH (concurrency=2, cpu_rate_limit=10, memory_limit=30, memory_shared_quota=0); +CREATE +CREATE ROLE role1_memory_test RESOURCE GROUP rg1_memory_test; +CREATE +CREATE ROLE role2_memory_test RESOURCE GROUP rg2_memory_test; +CREATE + +-- 7a) on QD +-- not enough memory +1: SET ROLE TO role1_memory_test; +SET +1: SELECT hold_memory_by_percent(0.2 / 0.3); +ERROR: Out of memory DETAIL: Resource group memory limit reached CONTEXT: SQL function "hold_memory_by_percent" statement 1 -2q: ... 1q: ... --- cleanup +-- alter rg2 memory_limit so last query has enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 20; +ALTER +-- system free chunks: 100% - 10% - 30% - 30% - 20% => 10% +-- memory available to one slot in rg1/rg2: 15% + 0 + 10% => 25% + +-- enough memory for allocating +1: SET ROLE TO role1_memory_test; +SET +1: SELECT hold_memory_by_percent(0.2 / 0.3); +hold_memory_by_percent +---------------------- +0 +(1 row) +1q: ... + +-- 7b) on QEs +-- not enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 30; +ALTER +1: SET ROLE TO role1_memory_test; +SET +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.3)=0; +ERROR: Out of memory (seg0 slice1 10.152.10.56:25432 pid=23131) +DETAIL: Resource group memory limit reached +CONTEXT: SQL function "hold_memory_by_percent" statement 1 +1q: ... + +-- alter rg2 memory_limit so last query has enough memory +ALTER RESOURCE GROUP rg2_memory_test SET memory_limit 20; +ALTER +-- system free chunks: 100% - 10% - 30% - 30% - 20% => 10% +-- memory available to one slot in rg1/rg2: 15% + 0 + 10% => 25% + +-- enough memory for allocating +1: SET ROLE TO role1_memory_test; +SET +1: SELECT count(null) FROM gp_dist_random('gp_id') t1 WHERE hold_memory_by_percent(0.2 / 0.3)=0; +count +----- +0 +(1 row) +1q: ... + DROP ROLE role1_memory_test; DROP +DROP ROLE role2_memory_test; +DROP DROP RESOURCE GROUP rg1_memory_test; DROP +DROP RESOURCE GROUP rg2_memory_test; +DROP + diff --git a/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source b/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source index db13567302c20dc88598bf41019e92f0aec81468..7243333bdfede42b105282d2dff9106158cf6736 100644 --- a/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source +++ b/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source @@ -298,3 +298,5 @@ DROP RESOURCE GROUP rg1_memory_test; DROP DROP RESOURCE GROUP rg2_memory_test; DROP +DROP VIEW memory_result; +DROP diff --git a/src/test/isolation2/sql/resgroup/resgroup_alter_memory_spill_ratio.sql b/src/test/isolation2/sql/resgroup/resgroup_alter_memory_spill_ratio.sql index 2423cfcf63a6893d9b54ae17d8602a6a3460e1fb..de53f2ed513a2cf17e14c6950a669af33d501f31 100644 --- a/src/test/isolation2/sql/resgroup/resgroup_alter_memory_spill_ratio.sql +++ b/src/test/isolation2/sql/resgroup/resgroup_alter_memory_spill_ratio.sql @@ -17,7 +17,7 @@ SELECT * FROM rg_spill_status; ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 20; SELECT * FROM rg_spill_status; --- positive, memory_spill_ratio range is [0, 100] +-- positive, memory_spill_ratio range is [0, 2147483647] ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 0; SELECT * FROM rg_spill_status; @@ -30,8 +30,8 @@ ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 20.0; ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO a; SELECT * FROM rg_spill_status; --- negative: memory_spill_ratio is larger than RESGROUP_MAX_MEMORY_SPILL_RATIO -ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 101; +-- negative: memory_spill_ratio is negative +ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO -1; SELECT * FROM rg_spill_status; -- cleanup diff --git a/src/test/isolation2/sql/resgroup/resgroup_set_memory_spill_ratio.sql b/src/test/isolation2/sql/resgroup/resgroup_set_memory_spill_ratio.sql index 9194ff7e167dd121a8b80ae9402c4f48964fba6f..9765851b1a7f8ac6f5d4951ad70a92ef16a510a8 100644 --- a/src/test/isolation2/sql/resgroup/resgroup_set_memory_spill_ratio.sql +++ b/src/test/isolation2/sql/resgroup/resgroup_set_memory_spill_ratio.sql @@ -30,7 +30,7 @@ SHOW MEMORY_SPILL_RATIO; SELECT 1; -- negative set to session level -SET MEMORY_SPILL_RATIO TO 101; +SET MEMORY_SPILL_RATIO TO -1; SHOW MEMORY_SPILL_RATIO; SELECT 1; diff --git a/src/test/isolation2/sql/resgroup/resgroup_syntax.sql b/src/test/isolation2/sql/resgroup/resgroup_syntax.sql index 5b70afd648c8675394f3e8f59be82a1d5fe00a71..6b579e96104de3a3601b8217dfb9c33a02f7ef1d 100644 --- a/src/test/isolation2/sql/resgroup/resgroup_syntax.sql +++ b/src/test/isolation2/sql/resgroup/resgroup_syntax.sql @@ -95,7 +95,7 @@ CREATE RESOURCE GROUP rg_test_group WITH (concurrency=0, cpu_rate_limit=10, memo -- negative: concurrency should be zero for cgroup audited resource group CREATE RESOURCE GROUP rg_test_group WITH (concurrency=1, cpu_rate_limit=10, memory_limit=10, memory_auditor="cgroup"); --- memory_spill_ratio range is [0, 100] +-- memory_spill_ratio range is [0, 2147483647] -- no limit on the sum of memory_shared_quota and memory_spill_ratio CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=10, memory_spill_ratio=0); DROP RESOURCE GROUP rg_test_group; @@ -136,7 +136,7 @@ DROP RESOURCE GROUP rg2_test_group; CREATE RESOURCE GROUP rg_test_group WITH (concurrency=0, cpu_rate_limit=10, memory_limit=10, memory_auditor="cgroup"); DROP RESOURCE GROUP rg_test_group; --- memory_spill_ratio range is [0, 100] +-- memory_spill_ratio range is [0, 2147483647] -- no limit on the sum of memory_shared_quota and memory_spill_ratio CREATE RESOURCE GROUP rg_test_group WITH (cpu_rate_limit=10, memory_limit=10, memory_shared_quota=0, memory_spill_ratio=1); DROP RESOURCE GROUP rg_test_group; diff --git a/src/test/isolation2/sql/resgroup/resgroup_unlimit_memory_spill_ratio.sql b/src/test/isolation2/sql/resgroup/resgroup_unlimit_memory_spill_ratio.sql index ea34f0900fe31b3143c9ef886e0277bbfd395e7a..2302e1cba1138912c76d839da36144a36199e3fc 100644 --- a/src/test/isolation2/sql/resgroup/resgroup_unlimit_memory_spill_ratio.sql +++ b/src/test/isolation2/sql/resgroup/resgroup_unlimit_memory_spill_ratio.sql @@ -19,10 +19,6 @@ CREATE RESOURCE GROUP rg_spill_test WITH (concurrency=10, cpu_rate_limit=20, memory_limit=20, memory_shared_quota=50, memory_spill_ratio=-1); DROP RESOURCE GROUP rg_spill_test; -CREATE RESOURCE GROUP rg_spill_test WITH -(concurrency=10, cpu_rate_limit=20, memory_limit=20, memory_shared_quota=50, memory_spill_ratio=101); -DROP RESOURCE GROUP rg_spill_test; - -- alter CREATE RESOURCE GROUP rg_spill_test WITH (concurrency=10, cpu_rate_limit=20, memory_limit=20, memory_shared_quota=50, memory_spill_ratio=20); @@ -31,7 +27,7 @@ ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 60; ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 0; ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 100; ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO -1; -ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 101; +ALTER RESOURCE GROUP rg_spill_test SET MEMORY_SPILL_RATIO 10000; DROP RESOURCE GROUP rg_spill_test; @@ -55,7 +51,7 @@ SET MEMORY_SPILL_RATIO TO -1; SHOW MEMORY_SPILL_RATIO; SELECT 1; -SET MEMORY_SPILL_RATIO TO 101; +SET MEMORY_SPILL_RATIO TO 10000; SHOW MEMORY_SPILL_RATIO; SELECT 1;