| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /*------------------------------------------------------------------------- |
| * |
| * meminstrumentation.h |
| * This file contains declarations for memory instrumentation utility |
| * functions. |
| * |
| * Portions Copyright (c) 2013, Greenplum inc |
| * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * $PostgreSQL: pgsql/src/include/utils/meminstrumentation.h,v 1.00 2013/03/22 14:57:00 rahmaf2 Exp $ |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #ifndef MEMACCOUNTING_H |
| #define MEMACCOUNTING_H |
| |
| #include "nodes/nodes.h" |
| #include "lib/stringinfo.h" /* StringInfo */ |
| |
| struct MemoryContextData; |
| |
| /* Macros to define the level of memory accounting to show in EXPLAIN ANALYZE */ |
| #define EXPLAIN_MEMORY_VERBOSITY_SUPPRESS 0 /* Suppress memory reporting in explain analyze */ |
| #define EXPLAIN_MEMORY_VERBOSITY_SUMMARY 1 /* Summary of memory usage for each owner in explain analyze */ |
| #define EXPLAIN_MEMORY_VERBOSITY_DETAIL 2 /* Detail memory accounting tree for each slice in explain analyze */ |
| |
| /* |
| * What level of details of the memory accounting information to show during EXPLAIN ANALYZE? |
| */ |
| extern int explain_memory_verbosity; |
| |
| /* |
| * Unique run id for memory profiling. May be just a start timestamp for a batch of queries such as TPCH |
| */ |
| extern char* memory_profiler_run_id; |
| |
| /* |
| * Dataset ID. Determined by the external script. One example could be, 1: TPCH, 2: TPCDS etc. |
| */ |
| extern char* memory_profiler_dataset_id; |
| |
| /* |
| * Which query of the query suite is running currently. E.g., query 21 of TPCH |
| */ |
| extern char* memory_profiler_query_id; |
| |
| /* |
| * Scale factor of TPCH/TPCDS etc. |
| */ |
| extern int memory_profiler_dataset_size; |
| |
| /* |
| * Should we save the memory usage information before resetting the memory accounting? |
| */ |
| extern bool gp_dump_memory_usage; |
| |
| /* |
| * Each memory account can assume one of the following memory |
| * owner types |
| */ |
| typedef enum MemoryOwnerType |
| { |
| /* Long-living accounts that survive reset */ |
| MEMORY_OWNER_TYPE_LogicalRoot = 10, |
| MEMORY_OWNER_TYPE_SharedChunkHeader = 11, |
| MEMORY_OWNER_TYPE_Rollover = 12, |
| MEMORY_OWNER_TYPE_MemAccount = 13, |
| /* End of long-living accounts */ |
| |
| /* Short-living accounts */ |
| MEMORY_OWNER_TYPE_Top = 101, |
| MEMORY_OWNER_TYPE_MainEntry = 102, |
| MEMORY_OWNER_TYPE_Parser = 103, |
| MEMORY_OWNER_TYPE_Planner = 104, |
| MEMORY_OWNER_TYPE_Optimizer = 105, |
| MEMORY_OWNER_TYPE_Dispatcher = 106, |
| MEMORY_OWNER_TYPE_Serializer = 107, |
| MEMORY_OWNER_TYPE_Deserializer = 108, |
| MEMORY_OWNER_TYPE_Resource_Negotiator = 109, |
| |
| MEMORY_OWNER_TYPE_EXECUTOR = 1000, |
| MEMORY_OWNER_TYPE_Exec_Result = 1001, |
| MEMORY_OWNER_TYPE_Exec_Append = 1002, |
| MEMORY_OWNER_TYPE_Exec_Sequence = 1003, |
| MEMORY_OWNER_TYPE_Exec_BitmapAnd = 1004, |
| MEMORY_OWNER_TYPE_Exec_BitmapOr = 1005, |
| MEMORY_OWNER_TYPE_Exec_SeqScan = 1006, |
| MEMORY_OWNER_TYPE_Exec_ExternalScan = 1007, |
| MEMORY_OWNER_TYPE_Exec_AppendOnlyScan = 1008, |
| MEMORY_OWNER_TYPE_Exec_TableScan = 1010, |
| MEMORY_OWNER_TYPE_Exec_DynamicTableScan = 1011, |
| MEMORY_OWNER_TYPE_Exec_IndexScan = 1012, |
| MEMORY_OWNER_TYPE_Exec_DynamicIndexScan = 1013, |
| MEMORY_OWNER_TYPE_Exec_BitmapIndexScan = 1014, |
| MEMORY_OWNER_TYPE_Exec_BitmapHeapScan = 1015, |
| MEMORY_OWNER_TYPE_Exec_BitmapAppendOnlyScan = 1016, |
| MEMORY_OWNER_TYPE_Exec_TidScan = 1017, |
| MEMORY_OWNER_TYPE_Exec_SubqueryScan = 1018, |
| MEMORY_OWNER_TYPE_Exec_FunctionScan = 1019, |
| MEMORY_OWNER_TYPE_Exec_TableFunctionScan = 1020, |
| MEMORY_OWNER_TYPE_Exec_ValuesScan = 1021, |
| MEMORY_OWNER_TYPE_Exec_NestLoop = 1022, |
| MEMORY_OWNER_TYPE_Exec_MergeJoin = 1023, |
| MEMORY_OWNER_TYPE_Exec_HashJoin = 1024, |
| MEMORY_OWNER_TYPE_Exec_Material = 1025, |
| MEMORY_OWNER_TYPE_Exec_Sort = 1026, |
| MEMORY_OWNER_TYPE_Exec_Agg = 1027, |
| MEMORY_OWNER_TYPE_Exec_Unique = 1028, |
| MEMORY_OWNER_TYPE_Exec_Hash = 1029, |
| MEMORY_OWNER_TYPE_Exec_SetOp = 1030, |
| MEMORY_OWNER_TYPE_Exec_Limit = 1031, |
| MEMORY_OWNER_TYPE_Exec_Motion = 1032, |
| MEMORY_OWNER_TYPE_Exec_ShareInputScan = 1033, |
| MEMORY_OWNER_TYPE_Exec_Window = 1034, |
| MEMORY_OWNER_TYPE_Exec_Repeat = 1035, |
| MEMORY_OWNER_TYPE_Exec_DML = 1036, |
| MEMORY_OWNER_TYPE_Exec_SplitUpdate = 1037, |
| MEMORY_OWNER_TYPE_Exec_RowTrigger = 1038, |
| MEMORY_OWNER_TYPE_Exec_AssertOp = 1039, |
| MEMORY_OWNER_TYPE_Exec_AlienShared = 1040, |
| MEMORY_OWNER_TYPE_Exec_BitmapTableScan = 1041, |
| MEMORY_OWNER_TYPE_Exec_PartitionSelector = 1042, |
| MEMORY_OWNER_TYPE_Exec_Plan_End, /* No explicit number. Automatically gets the last of executor enumeration */ |
| |
| } MemoryOwnerType; |
| |
| /**** |
| * The following are constants to define additional memory stats |
| * (in addition to memory accounts) during CSV dump of memory balance |
| */ |
| /* vmem reserved from memprot.c */ |
| #define MEMORY_STAT_TYPE_VMEM_RESERVED -1 |
| /* Peak memory observed from inside memory accounting among all allocations */ |
| #define MEMORY_STAT_TYPE_MEMORY_ACCOUNTING_PEAK -2 |
| /***************************************************************************/ |
| |
| struct MemoryAccount; |
| |
| extern struct MemoryAccount* ActiveMemoryAccount; |
| extern struct MemoryAccount* RolloverMemoryAccount; |
| extern struct MemoryAccount* AlienExecutorMemoryAccount; |
| extern struct MemoryAccount* SharedChunkHeadersMemoryAccount; |
| |
| extern uint64 MemoryAccountingOutstandingBalance; |
| extern uint64 MemoryAccountingPeakBalance; |
| |
| extern uint16 MemoryAccountingCurrentGeneration; |
| |
| /* MemoryAccount is the fundamental data structure to record memory usage */ |
| typedef struct MemoryAccount { |
| NodeTag type; |
| MemoryOwnerType ownerType; |
| |
| uint64 allocated; |
| uint64 freed; |
| uint64 peak; |
| /* |
| * Maximum targeted allocation for an owner. Peak usage can be tracked to |
| * check if the allocation is overshooting |
| */ |
| uint64 maxLimit; |
| |
| /* If this account requests the privilege to "disown" some of the allocation |
| * that would otherwise be charged to its account, then disownedMemoryAccount |
| * holds a hidden account which will be used for allocation during a "disowned" |
| * state (upon calling "DisownMemoryAccount()"). |
| */ |
| //struct MemoryAccount *disownedMemoryAccount; |
| struct MemoryAccount *parentAccount; |
| |
| /* |
| * To traverse the tree of MemoryAccount, start from the Top. Read the firstChild and then read the |
| * nextSibling of the firstChild. And continue this process. For each of the nextSibling, you can call |
| * firstChild to descend the tree. |
| */ |
| struct MemoryAccount* firstChild; |
| struct MemoryAccount* nextSibling; |
| } MemoryAccount; |
| |
| /* |
| * Instead of pointers to construct the tree, the SerializedMemoryAccount |
| * uses "serial" of each node and saves parent serial to construct the tree. |
| * This is required as we cannot serialize pointers. As an optimization, we |
| * can later on try to reuse the pointers themselves and treat them as integer |
| * to save the "serial" |
| */ |
| typedef struct SerializedMemoryAccount { |
| NodeTag type; |
| MemoryAccount memoryAccount; |
| |
| /* |
| * memoryAccountSerial and parentMemoryAccountSerial are used for serializing |
| * MemoryAccount. Note: we cannot serialize the tree using the pointers. |
| * Instead we serialize these "serial" and "parent serial" and construct the |
| * tree at the destination (e.g., dispatcher or any reporting tool). |
| */ |
| uint32 memoryAccountSerial; |
| /* If memoryAccountSerial == parentMemoryAccountSerial, then the node has NO parent */ |
| uint32 parentMemoryAccountSerial; |
| } SerializedMemoryAccount; |
| |
| /* |
| * START_MEMORY_ACCOUNT would switch to the specified newMemoryAccount, |
| * saving the oldActiveMemoryAccount. Must be paired with END_MEMORY_ACCOUNT |
| */ |
| #define START_MEMORY_ACCOUNT(newMemoryAccount) \ |
| do { \ |
| MemoryAccount *oldActiveMemoryAccount = NULL; \ |
| Assert(newMemoryAccount != NULL); \ |
| oldActiveMemoryAccount = ActiveMemoryAccount; \ |
| ActiveMemoryAccount = newMemoryAccount;\ |
| /* |
| * END_MEMORY_ACCOUNT would restore the previous memory account that was |
| * active at the time of START_MEMORY_ACCCOUNT call |
| */ |
| #define END_MEMORY_ACCOUNT() \ |
| ActiveMemoryAccount = oldActiveMemoryAccount;\ |
| } while (0); |
| |
| /* |
| * CREATE_EXECUTOR_MEMORY_ACCOUNT is a convenience macro to create a new |
| * operator specific memory account *if* the operator will be executed in |
| * the current slice, i.e., it is not part of some other slice (alien |
| * plan node). We assign a shared AlienExecutorMemoryAccount for plan nodes |
| * that will not be executed in current slice |
| */ |
| #define CREATE_EXECUTOR_MEMORY_ACCOUNT(isAlienPlanNode, planNode, NodeType) \ |
| (NULL != planNode->memoryAccount && MEMORY_OWNER_TYPE_Exec_##NodeType == planNode->memoryAccount->ownerType) ?\ |
| planNode->memoryAccount : \ |
| (isAlienPlanNode ? AlienExecutorMemoryAccount : \ |
| MemoryAccounting_CreateAccount(((Plan*)node)->operatorMemKB == 0 ? \ |
| work_mem : ((Plan*)node)->operatorMemKB, MEMORY_OWNER_TYPE_Exec_##NodeType)); |
| |
| /* |
| * SAVE_EXECUTOR_MEMORY_ACCOUNT saves an operator specific memory account |
| * into the PlanState of that operator |
| */ |
| #define SAVE_EXECUTOR_MEMORY_ACCOUNT(execState, curMemoryAccount)\ |
| Assert(NULL == ((PlanState *)execState)->plan->memoryAccount || \ |
| AlienExecutorMemoryAccount == ((PlanState *)execState)->plan->memoryAccount || \ |
| curMemoryAccount == ((PlanState *)execState)->plan->memoryAccount);\ |
| ((PlanState *)execState)->plan->memoryAccount = curMemoryAccount; |
| |
| extern struct MemoryAccount* |
| MemoryAccounting_CreateAccount(long maxLimit, enum MemoryOwnerType ownerType); |
| |
| extern MemoryAccount* |
| MemoryAccounting_SwitchAccount(struct MemoryAccount* desiredAccount); |
| |
| extern void |
| MemoryAccounting_Reset(void); |
| |
| extern void |
| MemoryAccounting_ResetPeakBalance(void); |
| |
| extern uint32 |
| MemoryAccounting_Serialize(StringInfoData* buffer); |
| |
| extern SerializedMemoryAccount* |
| MemoryAccounting_Deserialize(const void *serializedBits, |
| uint32 memoryAccountCount); |
| |
| extern uint64 |
| MemoryAccounting_GetPeak(MemoryAccount *memoryAccount); |
| |
| extern uint64 |
| MemoryAccounting_GetBalance(MemoryAccount *memoryAccount); |
| |
| extern void |
| MemoryAccounting_ToString(MemoryAccount *root, StringInfoData *str, |
| uint32 indentation); |
| |
| extern void |
| MemoryAccounting_SaveToFile(int currentSliceId); |
| |
| extern uint32 |
| MemoryAccounting_SaveToLog(void); |
| |
| extern const char* |
| MemoryAccounting_GetAccountName(MemoryAccount *memoryAccount); |
| |
| extern void |
| MemoryAccounting_ToCSV(MemoryAccount *root, StringInfoData *str, char *prefix); |
| |
| extern void |
| MemoryAccounting_PrettyPrint(void); |
| /* |
| * MemoryAccountIsValid |
| * True iff memory account is valid. |
| */ |
| #define MemoryAccountIsValid(memoryAccount) \ |
| ((memoryAccount) != NULL && \ |
| ( IsA((memoryAccount), MemoryAccount) )) |
| |
| #endif /* MEMACCOUNTING_H */ |