TDengine/source/util/test/memPoolTest.cpp

1370 lines
45 KiB
C++
Raw Normal View History

2024-08-02 08:08:19 +00:00
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <gtest/gtest.h>
#include <iostream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wformat"
#include <addr_any.h>
#ifdef WINDOWS
#define TD_USE_WINSOCK
#endif
#include "os.h"
2024-08-07 11:22:01 +00:00
#include "thash.h"
#include "theap.h"
2024-08-02 08:08:19 +00:00
#include "taos.h"
#include "tdef.h"
#include "tvariant.h"
#include "stub.h"
2024-11-07 08:46:18 +00:00
#include "../inc/tmempoolInt.h"
2024-08-02 08:08:19 +00:00
namespace {
2024-11-15 09:05:46 +00:00
#define MPT_PRINTF(param, ...) (void)printf("[%" PRId64 ",%" PRId64 "] " param, mptCtx.caseLoop, mptCtx.jobLoop, __VA_ARGS__)
2024-08-30 10:13:35 +00:00
#define MPT_MAX_MEM_ACT_TIMES 300
2024-08-16 10:22:31 +00:00
#define MPT_MAX_SESSION_NUM 100
#define MPT_MAX_JOB_NUM 100
2024-08-07 11:22:01 +00:00
#define MPT_MAX_THREAD_NUM 100
2024-08-16 10:22:31 +00:00
#define MPT_MAX_JOB_LOOP_TIMES 100
2024-08-07 11:22:01 +00:00
#define MPT_DEFAULT_RESERVE_MEM_PERCENT 20
#define MPT_MIN_RESERVE_MEM_SIZE (512 * 1048576UL)
#define MPT_MIN_MEM_POOL_SIZE (1048576UL)
#define MPT_MAX_RETIRE_JOB_NUM 10000
2024-11-15 02:16:15 +00:00
enum {
MPT_READ = 1,
MPT_WRITE,
};
2024-08-02 08:08:19 +00:00
threadlocal void* mptThreadPoolHandle = NULL;
threadlocal void* mptThreadPoolSession = NULL;
2024-11-15 02:16:15 +00:00
#define TD_RWLATCH_WRITE_FLAG_COPY 0x40000000
#define MPT_LOCK(type, _lock) \
do { \
if (MPT_READ == (type)) { \
if (atomic_load_32((_lock)) < 0) { \
uError("invalid lock value before read lock"); \
break; \
} \
taosRLockLatch(_lock); \
if (atomic_load_32((_lock)) <= 0) { \
uError("invalid lock value after read lock"); \
break; \
} \
} else { \
if (atomic_load_32((_lock)) < 0) { \
uError("invalid lock value before write lock"); \
break; \
} \
taosWLockLatch(_lock); \
if (atomic_load_32((_lock)) != TD_RWLATCH_WRITE_FLAG_COPY) { \
uError("invalid lock value after write lock"); \
break; \
} \
} \
} while (0)
#define MPT_UNLOCK(type, _lock) \
do { \
if (MPT_READ == (type)) { \
if (atomic_load_32((_lock)) <= 0) { \
uError("invalid lock value before read unlock"); \
break; \
} \
taosRUnLockLatch(_lock); \
if (atomic_load_32((_lock)) < 0) { \
uError("invalid lock value after read unlock"); \
break; \
} \
} else { \
if (atomic_load_32((_lock)) != TD_RWLATCH_WRITE_FLAG_COPY) { \
uError("invalid lock value before write unlock"); \
break; \
} \
taosWUnLockLatch(_lock); \
if (atomic_load_32((_lock)) < 0) { \
uError("invalid lock value after write unlock"); \
break; \
} \
} \
} while (0)
2024-08-07 11:22:01 +00:00
#define MPT_SET_TEID(id, tId, eId) \
do { \
*(uint64_t *)(id) = (tId); \
*(uint32_t *)((char *)(id) + sizeof(tId)) = (eId); \
} while (0)
2024-11-13 11:19:00 +00:00
#define MPT_SET_QCID(id, qId, cId) \
do { \
*(uint64_t *)(id) = (qId); \
*(uint64_t *)((char *)(id) + sizeof(qId)) = (cId); \
} while (0)
2024-08-02 08:08:19 +00:00
#define mptEnableMemoryPoolUsage(_pool, _session) do { mptThreadPoolHandle = _pool; mptThreadPoolSession = _session; } while (0)
2024-11-12 00:42:54 +00:00
#define mptDisableMemoryPoolUsage() (mptThreadPoolHandle = NULL, mptThreadPoolSession = NULL)
#define mptSaveDisableMemoryPoolUsage(_handle) do { (_handle) = mptThreadPoolHandle; mptThreadPoolHandle = NULL; } while (0)
#define mptRestoreEnableMemoryPoolUsage(_handle) (mptThreadPoolHandle = (_handle))
2024-08-02 08:08:19 +00:00
#define mptMemoryMalloc(_size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolMalloc(mptThreadPoolHandle, mptThreadPoolSession, _size, __FILE__, __LINE__)) : (taosMemMalloc(_size)))
#define mptMemoryCalloc(_num, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolCalloc(mptThreadPoolHandle, mptThreadPoolSession, _num, _size, __FILE__, __LINE__)) : (taosMemCalloc(_num, _size)))
#define mptMemoryRealloc(_ptr, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolRealloc(mptThreadPoolHandle, mptThreadPoolSession, _ptr, _size, __FILE__, __LINE__)) : (taosMemRealloc(_ptr, _size)))
#define mptStrdup(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolStrdup(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosStrdupi(_ptr)))
2024-08-16 10:22:31 +00:00
#define mptStrndup(_ptr, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolStrndup(mptThreadPoolHandle, mptThreadPoolSession, _ptr, _size, (char*)__FILE__, __LINE__)) : (taosStrndupi(_ptr, _size)))
#define mptMemoryFree(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolFree(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosMemFree(_ptr)))
#define mptMemorySize(_ptr) ((NULL != mptThreadPoolHandle) ? (taosMemPoolGetMemorySize(mptThreadPoolHandle, mptThreadPoolSession, _ptr, __FILE__, __LINE__)) : (taosMemSize(_ptr)))
2024-08-16 10:22:31 +00:00
#define mptMemoryTrim(_size, _trimed) ((NULL != mptThreadPoolHandle) ? (taosMemPoolTrim(mptThreadPoolHandle, mptThreadPoolSession, _size, __FILE__, __LINE__, _trimed)) : (taosMemTrim(_size, _trimed)))
#define mptMemoryMallocAlign(_alignment, _size) ((NULL != mptThreadPoolHandle) ? (taosMemPoolMallocAlign(mptThreadPoolHandle, mptThreadPoolSession, _alignment, _size, __FILE__, __LINE__)) : (taosMemMallocAlign(_alignment, _size)))
2024-08-02 08:08:19 +00:00
2024-08-07 11:22:01 +00:00
enum {
MPT_SMALL_MSIZE = 0,
MPT_BIG_MSIZE,
};
typedef struct {
int32_t jobNum;
int32_t sessionNum;
bool memSize[2];
bool jobQuotaRetire;
bool poolRetire;
} SMPTCaseParam;
2024-08-02 08:08:19 +00:00
typedef struct SMPTJobInfo {
int8_t retired;
int32_t errCode;
SMemPoolJob* memInfo;
2024-08-07 11:22:01 +00:00
void* pCtx;
2024-11-15 02:16:15 +00:00
SRWLatch lock;
int8_t destroyed;
SHashObj* pSessions;
2024-08-02 08:08:19 +00:00
} SMPTJobInfo;
typedef struct {
2024-08-16 10:22:31 +00:00
int32_t taskActTimes;
2024-08-08 10:31:33 +00:00
int32_t caseLoopTimes;
2024-08-16 10:22:31 +00:00
int32_t jobExecTimes;
int32_t jobNum;
int32_t jobTaskNum;
2024-08-08 10:31:33 +00:00
int64_t maxSingleAllocSize;
char* pSrcString;
2024-08-16 10:22:31 +00:00
bool printExecDetail;
2024-08-08 10:31:33 +00:00
bool printInputRow;
} SMPTestCtrl;
2024-08-02 08:08:19 +00:00
typedef struct {
2024-08-07 11:22:01 +00:00
void* p;
int64_t size;
} SMPTestMemInfo;
typedef struct {
2024-08-16 10:22:31 +00:00
uint64_t taskId;
2024-08-08 10:31:33 +00:00
SRWLatch taskExecLock;
2024-11-15 02:16:15 +00:00
bool destoryed;
2024-08-07 11:22:01 +00:00
int64_t poolMaxUsedSize;
int64_t poolTotalUsedSize;
SMPStatDetail stat;
int32_t memIdx;
2024-08-16 10:22:31 +00:00
SMPTestMemInfo* pMemList;
2024-08-07 11:22:01 +00:00
int64_t npSize;
int32_t npMemIdx;
2024-08-16 10:22:31 +00:00
SMPTestMemInfo* npMemList;
2024-08-07 11:22:01 +00:00
bool taskFreed;
2024-08-16 10:22:31 +00:00
int32_t lastAct;
2024-08-07 11:22:01 +00:00
} SMPTestTaskCtx;
typedef struct {
SRWLatch jobExecLock;
int32_t jobIdx;
2024-08-08 10:31:33 +00:00
int64_t jobId;
void* pSessions[MPT_MAX_SESSION_NUM];
2024-08-07 11:22:01 +00:00
int32_t taskNum;
SMPTestTaskCtx taskCtxs[MPT_MAX_SESSION_NUM];
2024-08-07 11:22:01 +00:00
2024-08-08 10:31:33 +00:00
int32_t taskRunningNum;
2024-08-07 11:22:01 +00:00
SMPTJobInfo* pJob;
int32_t jobStatus;
} SMPTestJobCtx;
typedef struct {
2024-11-07 08:46:18 +00:00
int32_t jobQuota;
2024-11-06 11:26:14 +00:00
bool reserveMode;
int64_t upperLimitSize;
2024-11-07 08:46:18 +00:00
int32_t reserveSize;
2024-08-07 11:22:01 +00:00
int32_t threadNum;
int32_t randTask;
} SMPTestParam;
typedef struct {
2024-08-16 10:22:31 +00:00
int32_t idx;
2024-08-08 10:31:33 +00:00
TdThread threadFp;
bool allJobs;
bool autoJob;
2024-08-07 11:22:01 +00:00
} SMPTestThread;
2024-08-02 08:08:19 +00:00
typedef struct SMPTestCtx {
2024-08-08 10:31:33 +00:00
int64_t qId;
2024-08-16 10:22:31 +00:00
int64_t tId;
SHashObj* pJobs;
BoundedQueue* pJobQueue;
2024-08-07 11:22:01 +00:00
SMPTestThread threadCtxs[MPT_MAX_THREAD_NUM];
2024-11-15 09:05:46 +00:00
TdThread dropThreadFp;
int32_t jobNum;
2024-08-16 10:22:31 +00:00
SMPTestJobCtx* jobCtxs;
2024-08-07 11:22:01 +00:00
SMPTestParam param;
2024-11-15 09:05:46 +00:00
int8_t testDone;
int64_t caseLoop;
int64_t jobLoop;
2024-08-02 08:08:19 +00:00
} SMPTestCtx;
SMPTestCtx mptCtx = {0};
2024-08-08 10:31:33 +00:00
SMPTestCtrl mptCtrl = {0};
2024-08-02 08:08:19 +00:00
2024-08-07 11:22:01 +00:00
#if 0
2024-08-02 08:08:19 +00:00
void joinTestReplaceRetrieveFp() {
static Stub stub;
stub.set(getNextBlockFromDownstreamRemain, getDummyInputBlock);
{
#ifdef WINDOWS
AddrAny any;
std::map<std::string, void *> result;
any.get_func_addr("getNextBlockFromDownstreamRemain", result);
for (const auto &f : result) {
stub.set(f.second, getDummyInputBlock);
}
#endif
#ifdef LINUX
AddrAny any("libexecutor.so");
std::map<std::string, void *> result;
any.get_global_func_addr_dynsym("^getNextBlockFromDownstreamRemain$", result);
for (const auto &f : result) {
stub.set(f.second, getDummyInputBlock);
}
#endif
}
}
2024-08-07 11:22:01 +00:00
#endif
2024-08-02 08:08:19 +00:00
void mptInitLogFile() {
const char *defaultLogFileNamePrefix = "mplog";
const int32_t maxLogFileNum = 10;
tsAsyncLog = 0;
qDebugFlag = 159;
2024-08-16 10:22:31 +00:00
uDebugFlag = 159;
tsNumOfLogLines = INT32_MAX;
tsLogKeepDays = 10;
2024-08-02 08:08:19 +00:00
TAOS_STRCPY(tsLogDir, TD_LOG_DIR_PATH);
2024-11-06 11:26:14 +00:00
if (taosInitLog(defaultLogFileNamePrefix, maxLogFileNum, false) < 0) {
2024-08-07 11:22:01 +00:00
MPT_PRINTF("failed to open log file in directory:%s\n", tsLogDir);
2024-08-02 08:08:19 +00:00
}
}
static bool mptJobMemSizeCompFn(void* l, void* r, void* param) {
2024-08-07 11:22:01 +00:00
SMPTJobInfo* left = (SMPTJobInfo*)l;
SMPTJobInfo* right = (SMPTJobInfo*)r;
2024-08-02 08:08:19 +00:00
if (atomic_load_8(&right->retired)) {
return true;
}
return atomic_load_64(&right->memInfo->allocMemSize) < atomic_load_64(&left->memInfo->allocMemSize);
}
2024-08-16 10:22:31 +00:00
void mptDeleteJobQueueData(void* pData) {
SMPTJobInfo* pJob = (SMPTJobInfo*)pData;
taosHashRelease(mptCtx.pJobs, pJob);
}
2024-08-02 08:08:19 +00:00
void mptInit() {
2024-11-12 00:42:54 +00:00
osDefaultInit();
2024-08-02 08:08:19 +00:00
mptInitLogFile();
2024-08-16 10:22:31 +00:00
2024-11-15 09:05:46 +00:00
mptCtrl.caseLoopTimes = 100000;
2024-08-30 10:13:35 +00:00
mptCtrl.taskActTimes = 0;
2024-08-16 10:22:31 +00:00
mptCtrl.maxSingleAllocSize = 104857600;
mptCtrl.jobNum = 100;
2024-11-15 09:05:46 +00:00
mptCtrl.jobExecTimes = 10;
2024-08-30 10:13:35 +00:00
mptCtrl.jobTaskNum = 0;
2024-08-02 08:08:19 +00:00
mptCtx.pJobs = taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_ENTRY_LOCK);
ASSERT_TRUE(NULL != mptCtx.pJobs);
2024-08-16 10:22:31 +00:00
mptCtx.pJobQueue = createBoundedQueue(10000, mptJobMemSizeCompFn, mptDeleteJobQueueData, NULL);
2024-08-02 08:08:19 +00:00
ASSERT_TRUE(NULL != mptCtx.pJobQueue);
2024-11-06 11:26:14 +00:00
mptCtx.jobCtxs = (SMPTestJobCtx*)taosMemoryCalloc(MPT_MAX_JOB_NUM, sizeof(*mptCtx.jobCtxs));
2024-08-16 10:22:31 +00:00
ASSERT_TRUE(NULL != mptCtx.jobCtxs);
2024-08-08 10:31:33 +00:00
mptCtrl.pSrcString = (char*)taosMemoryMalloc(mptCtrl.maxSingleAllocSize);
ASSERT_TRUE(NULL != mptCtrl.pSrcString);
memset(mptCtrl.pSrcString, 'P', mptCtrl.maxSingleAllocSize - 1);
mptCtrl.pSrcString[mptCtrl.maxSingleAllocSize - 1] = 0;
2024-08-02 08:08:19 +00:00
}
2024-11-15 09:05:46 +00:00
void mptDestroyJobInfo(SMPTJobInfo* pJob) {
taosMemFree(pJob->memInfo);
taosHashCleanup(pJob->pSessions);
}
void mptDestroySession(uint64_t qId, int64_t tId, int32_t eId, int32_t taskIdx, SMPTestJobCtx* pJobCtx, void* session) {
SMPTJobInfo *pJobInfo = pJobCtx->pJob;
char id[sizeof(tId) + sizeof(eId) + 1] = {0};
MPT_SET_TEID(id, tId, eId);
int32_t remainSessions = 0;
(void)taosHashRemove(pJobInfo->pSessions, id, sizeof(id));
taosMemPoolDestroySession(gMemPoolHandle, session, &remainSessions);
if (0 == remainSessions) {
MPT_LOCK(MPT_WRITE, &pJobInfo->lock);
if (0 == taosHashGetSize(pJobInfo->pSessions)) {
atomic_store_8(&pJobInfo->destroyed, 1);
uDebug("JOB:0x%x idx:%d destroyed, code:0x%x", pJobCtx->jobId, pJobCtx->jobIdx, pJobInfo->errCode);
mptDestroyJobInfo(pJobInfo);
MPT_UNLOCK(MPT_WRITE, &pJobInfo->lock);
pJobCtx->pJob = NULL;
(void)taosHashRemove(mptCtx.pJobs, &qId, sizeof(qId));
uInfo("the whole query job removed");
} else {
MPT_UNLOCK(MPT_WRITE, &pJobInfo->lock);
}
}
}
void mptDestroyTaskCtx(SMPTestJobCtx* pJobCtx, int32_t taskIdx) {
2024-11-12 00:42:54 +00:00
assert(gMemPoolHandle);
2024-08-16 10:22:31 +00:00
2024-11-15 09:05:46 +00:00
SMPTestTaskCtx* pTask = &pJobCtx->taskCtxs[taskIdx];
mptEnableMemoryPoolUsage(gMemPoolHandle, pJobCtx->pSessions[taskIdx]);
2024-08-07 11:22:01 +00:00
for (int32_t i = 0; i < pTask->memIdx; ++i) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memFree.exec++;
pTask->stat.bytes.memFree.exec+=mptMemorySize(pTask->pMemList[i].p);
pTask->stat.bytes.memFree.succ+=mptMemorySize(pTask->pMemList[i].p);
2024-08-16 10:22:31 +00:00
mptMemoryFree(pTask->pMemList[i].p);
pTask->pMemList[i].p = NULL;
2024-08-07 11:22:01 +00:00
}
2024-08-16 10:22:31 +00:00
mptDisableMemoryPoolUsage();
2024-11-15 09:05:46 +00:00
mptDestroySession(pJobCtx->jobId, pJobCtx->taskCtxs[taskIdx].taskId, 0, taskIdx, pJobCtx, pJobCtx->pSessions[taskIdx]);
pJobCtx->pSessions[taskIdx] = NULL;
2024-08-16 10:22:31 +00:00
2024-08-07 11:22:01 +00:00
for (int32_t i = 0; i < pTask->npMemIdx; ++i) {
taosMemFreeClear(pTask->npMemList[i].p);
}
2024-08-16 10:22:31 +00:00
taosMemFreeClear(pTask->pMemList);
taosMemFreeClear(pTask->npMemList);
2024-11-15 02:16:15 +00:00
pTask->destoryed = true;
2024-08-07 11:22:01 +00:00
}
2024-08-08 10:31:33 +00:00
int32_t mptInitJobInfo(uint64_t qId, SMPTJobInfo* pJob) {
pJob->pSessions= taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_ENTRY_LOCK);
if (NULL == pJob->pSessions) {
uError("fail to init session hash, code: 0x%x", terrno);
return terrno;
}
2024-11-13 11:19:00 +00:00
int32_t code = taosMemPoolCallocJob(qId, 0, (void**)&pJob->memInfo);
2024-08-08 10:31:33 +00:00
if (TSDB_CODE_SUCCESS != code) {
taosHashCleanup(pJob->pSessions);
pJob->pSessions = NULL;
return code;
}
return code;
}
int32_t mptInitSession(uint64_t qId, uint64_t tId, int32_t eId, SMPTestJobCtx* pJobCtx, void** ppSession) {
int32_t code = TSDB_CODE_SUCCESS;
SMPTJobInfo* pJob = NULL;
while (true) {
pJob = (SMPTJobInfo*)taosHashAcquire(mptCtx.pJobs, &qId, sizeof(qId));
if (NULL == pJob) {
SMPTJobInfo jobInfo = {0};
code = mptInitJobInfo(qId, &jobInfo);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
code = taosHashPut(mptCtx.pJobs, &qId, sizeof(qId), &jobInfo, sizeof(jobInfo));
if (TSDB_CODE_SUCCESS != code) {
mptDestroyJobInfo(&jobInfo);
if (TSDB_CODE_DUP_KEY == code) {
code = TSDB_CODE_SUCCESS;
continue;
}
return code;
}
pJob = (SMPTJobInfo*)taosHashAcquire(mptCtx.pJobs, &qId, sizeof(qId));
if (NULL == pJob) {
uError("QID:0x%" PRIx64 " not in joj hash, may be dropped", qId);
return TSDB_CODE_QRY_JOB_NOT_EXIST;
}
}
break;
}
pJobCtx->pJob = pJob;
pJob->pCtx = pJobCtx;
2024-11-15 09:05:46 +00:00
char id[sizeof(tId) + sizeof(eId) + 1] = {0};
2024-08-08 10:31:33 +00:00
MPT_SET_TEID(id, tId, eId);
2024-11-13 11:19:00 +00:00
assert(0 == taosMemPoolInitSession(gMemPoolHandle, ppSession, pJob->memInfo, id));
2024-08-08 10:31:33 +00:00
assert(0 == taosHashPut(pJob->pSessions, id, sizeof(id), ppSession, POINTER_BYTES));
_return:
if (NULL != pJob) {
taosHashRelease(mptCtx.pJobs, pJob);
}
return code;
}
2024-08-16 10:22:31 +00:00
void mptInitTask(int32_t idx, int32_t eId, SMPTestJobCtx* pJob) {
pJob->taskCtxs[idx].taskId = atomic_add_fetch_64(&mptCtx.tId, 1);
ASSERT_TRUE(0 == mptInitSession(pJob->jobId, pJob->taskCtxs[idx].taskId, eId, pJob, &pJob->pSessions[idx]));
2024-11-06 11:26:14 +00:00
pJob->taskCtxs[idx].pMemList = (SMPTestMemInfo*)taosMemoryCalloc(MPT_MAX_MEM_ACT_TIMES, sizeof(*pJob->taskCtxs[idx].pMemList));
2024-08-16 10:22:31 +00:00
ASSERT_TRUE(NULL != pJob->taskCtxs[idx].pMemList);
2024-11-06 11:26:14 +00:00
pJob->taskCtxs[idx].npMemList = (SMPTestMemInfo*)taosMemoryCalloc(MPT_MAX_MEM_ACT_TIMES, sizeof(*pJob->taskCtxs[idx].npMemList));
2024-08-16 10:22:31 +00:00
ASSERT_TRUE(NULL != pJob->taskCtxs[idx].npMemList);
2024-11-15 02:16:15 +00:00
pJob->taskCtxs[idx].destoryed = false;
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x idx:%d initialized", pJob->jobId, pJob->taskCtxs[idx].taskId, idx);
2024-08-08 10:31:33 +00:00
}
void mptInitJob(int32_t idx) {
SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[idx];
pJobCtx->jobIdx = idx;
pJobCtx->jobId = atomic_add_fetch_64(&mptCtx.qId, 1);
2024-11-14 09:38:20 +00:00
pJobCtx->taskNum = (mptCtrl.jobTaskNum) ? mptCtrl.jobTaskNum : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_SESSION_NUM/10)) : (taosRand() % MPT_MAX_SESSION_NUM)) + 1;
2024-08-08 10:31:33 +00:00
for (int32_t i = 0; i < pJobCtx->taskNum; ++i) {
2024-08-16 10:22:31 +00:00
mptInitTask(i, 0, pJobCtx);
assert(pJobCtx->pJob);
2024-08-08 10:31:33 +00:00
}
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x idx:%d initialized, taskNum:%d", pJobCtx->jobId, idx, pJobCtx->taskNum);
2024-08-08 10:31:33 +00:00
}
2024-11-15 02:16:15 +00:00
2024-11-15 09:05:46 +00:00
void mptDestroyTask(SMPTestJobCtx* pJobCtx, int32_t taskIdx) {
SMPStatDetail* pStat = NULL;
int64_t allocSize = 0;
taosMemPoolGetSessionStat(pJobCtx->pSessions[taskIdx], &pStat, &allocSize, NULL);
int64_t usedSize = MEMPOOL_GET_USED_SIZE(pStat);
assert(allocSize == usedSize);
assert(0 == memcmp(pStat, &pJobCtx->taskCtxs[taskIdx].stat, sizeof(*pStat)));
mptDestroyTaskCtx(pJobCtx, taskIdx);
2024-11-15 02:16:15 +00:00
}
2024-08-08 10:31:33 +00:00
int32_t mptDestroyJob(SMPTestJobCtx* pJobCtx, bool reset) {
if (taosWTryLockLatch(&pJobCtx->jobExecLock)) {
return -1;
}
2024-08-16 10:22:31 +00:00
uint64_t jobId = pJobCtx->jobId;
2024-08-07 11:22:01 +00:00
for (int32_t i = 0; i < pJobCtx->taskNum; ++i) {
2024-11-15 02:16:15 +00:00
if (!pJobCtx->taskCtxs[i].destoryed) {
2024-11-15 09:05:46 +00:00
mptDestroyTask(pJobCtx, i);
2024-11-15 02:16:15 +00:00
}
2024-08-07 11:22:01 +00:00
}
2024-08-16 10:22:31 +00:00
2024-11-15 02:16:15 +00:00
//mptDestroyJobInfo(pJobCtx->pJob);
//(void)taosHashRemove(mptCtx.pJobs, &pJobCtx->jobId, sizeof(pJobCtx->jobId));
2024-08-16 10:22:31 +00:00
2024-08-07 11:22:01 +00:00
if (reset) {
2024-08-16 10:22:31 +00:00
int32_t jobIdx = pJobCtx->jobIdx;
2024-08-07 11:22:01 +00:00
memset((char*)pJobCtx + sizeof(pJobCtx->jobExecLock), 0, sizeof(SMPTestJobCtx) - sizeof(pJobCtx->jobExecLock));
2024-08-16 10:22:31 +00:00
mptInitJob(jobIdx);
2024-08-07 11:22:01 +00:00
}
taosWUnLockLatch(&pJobCtx->jobExecLock);
2024-08-08 10:31:33 +00:00
2024-08-16 10:22:31 +00:00
MPT_PRINTF(" JOB:0x%x retired\n", jobId);
2024-08-08 10:31:33 +00:00
return 0;
2024-08-07 11:22:01 +00:00
}
void mptCheckCompareJobInfo(SMPTestJobCtx* pJobCtx) {
}
2024-08-08 10:31:33 +00:00
int32_t mptResetJob(SMPTestJobCtx* pJobCtx) {
2024-11-15 09:05:46 +00:00
if (NULL == pJobCtx->pJob) {
return -1;
}
2024-08-08 10:31:33 +00:00
if (atomic_load_8(&pJobCtx->pJob->retired)) {
2024-08-16 10:22:31 +00:00
int32_t taskRunning = atomic_load_32(&pJobCtx->taskRunningNum);
if (0 == taskRunning) {
2024-08-08 10:31:33 +00:00
return mptDestroyJob(pJobCtx, true);
} else {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x retired but will not destroy cause of task running, num:%d", pJobCtx->jobId, taskRunning);
2024-08-08 10:31:33 +00:00
return -1;
}
}
return 0;
2024-08-07 11:22:01 +00:00
}
void mptRetireJob(SMPTJobInfo* pJob) {
SMPTestJobCtx* pCtx = (SMPTestJobCtx*)pJob->pCtx;
2024-08-16 10:22:31 +00:00
2024-11-13 11:19:00 +00:00
int32_t taskRunning = atomic_load_32(&pCtx->taskRunningNum);
if (0 == taskRunning) {
mptDestroyJob(pCtx, false);
} else {
uDebug("JOB:0x%x retired but will not destroy cause of task running, num:%d", pCtx->jobId, taskRunning);
}
2024-08-07 11:22:01 +00:00
}
2024-08-16 10:22:31 +00:00
int32_t mptGetMemPoolMaxMemSize(void* pHandle, int64_t* maxSize) {
int64_t freeSize = 0;
int64_t usedSize = 0;
bool needEnd = false;
taosMemPoolGetUsedSizeBegin(pHandle, &usedSize, &needEnd);
int32_t code = taosGetSysAvailMemory(&freeSize);
if (needEnd) {
taosMemPoolGetUsedSizeEnd(pHandle);
}
if (TSDB_CODE_SUCCESS != code) {
uError("get system avaiable memory size failed, error: 0x%x", code);
return code;
}
int64_t totalSize = freeSize + usedSize;
2024-08-07 11:22:01 +00:00
int64_t reserveSize = TMAX(totalSize * MPT_DEFAULT_RESERVE_MEM_PERCENT / 100 / 1048576UL * 1048576UL, MPT_MIN_RESERVE_MEM_SIZE);
int64_t availSize = (totalSize - reserveSize) / 1048576UL * 1048576UL;
if (availSize < MPT_MIN_MEM_POOL_SIZE) {
uError("too little available query memory, totalAvailable: %" PRId64 ", reserveSize: %" PRId64, totalSize, reserveSize);
return TSDB_CODE_QRY_TOO_FEW_AVAILBLE_MEM;
}
2024-08-16 10:22:31 +00:00
uDebug("new pool maxSize:%" PRId64 ", usedSize:%" PRId64 ", freeSize:%" PRId64, availSize, usedSize, freeSize);
2024-08-07 11:22:01 +00:00
*maxSize = availSize;
return TSDB_CODE_SUCCESS;
}
2024-11-07 08:46:18 +00:00
void mptRetireJobsCb(int64_t retireSize, int32_t errCode) {
2024-08-07 11:22:01 +00:00
SMPTJobInfo* pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, NULL);
2024-11-06 11:26:14 +00:00
uint64_t jobId = 0;
2024-08-02 08:08:19 +00:00
int64_t retiredSize = 0;
2024-11-06 11:26:14 +00:00
while (retiredSize < retireSize && NULL != pJob) {
2024-08-02 08:08:19 +00:00
if (atomic_load_8(&pJob->retired)) {
2024-11-06 11:26:14 +00:00
pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, NULL);
2024-08-02 08:08:19 +00:00
continue;
}
if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) {
int64_t aSize = atomic_load_64(&pJob->memInfo->allocMemSize);
2024-11-06 11:26:14 +00:00
jobId = pJob->memInfo->jobId;
2024-08-02 08:08:19 +00:00
mptRetireJob(pJob);
retiredSize += aSize;
2024-08-16 10:22:31 +00:00
uDebug("QID:0x%" PRIx64 " job retired cause of mid level memory retire, usedSize:%" PRId64 ", retireSize:%" PRId64 ", retiredSize:%" PRId64,
jobId, aSize, retireSize, retiredSize);
2024-08-02 08:08:19 +00:00
}
2024-11-06 11:26:14 +00:00
pJob = (SMPTJobInfo*)taosHashIterate(mptCtx.pJobs, NULL);
2024-08-02 08:08:19 +00:00
}
}
2024-11-13 11:19:00 +00:00
void mptRetireJobCb(uint64_t jobId, uint64_t clientId, int32_t errCode) {
char id[sizeof(jobId) + sizeof(clientId) + 1] = {0};
MPT_SET_QCID(id, jobId, clientId);
SMPTJobInfo* pJob = (SMPTJobInfo*)taosHashGet(mptCtx.pJobs, id, sizeof(id));
2024-08-02 08:08:19 +00:00
if (NULL == pJob) {
2024-11-13 11:19:00 +00:00
uError("QID:0x%" PRIx64 " CID:0x%" PRIx64 " fail to get job from job hash", jobId, clientId);
2024-08-02 08:08:19 +00:00
return;
}
if (0 == atomic_val_compare_exchange_32(&pJob->errCode, 0, errCode) && 0 == atomic_val_compare_exchange_8(&pJob->retired, 0, 1)) {
2024-11-13 11:19:00 +00:00
uInfo("QID:0x%" PRIx64 " CID:0x%" PRIx64 " mark retired, errCode: 0x%x, allocSize:%" PRId64, jobId, clientId, errCode, atomic_load_64(&pJob->memInfo->allocMemSize));
2024-08-02 08:08:19 +00:00
} else {
2024-11-13 11:19:00 +00:00
uDebug("QID:0x%" PRIx64 " CID:0x%" PRIx64 " already retired, retired: %d, errCode: 0x%x, allocSize:%" PRId64, jobId, clientId, atomic_load_8(&pJob->retired), atomic_load_32(&pJob->errCode), atomic_load_64(&pJob->memInfo->allocMemSize));
2024-08-02 08:08:19 +00:00
}
}
2024-08-08 10:31:33 +00:00
void mptInitPool(void) {
2024-11-12 00:42:54 +00:00
assert(0 == taosMemoryPoolInit(mptRetireJobsCb, mptRetireJobCb));
2024-08-02 08:08:19 +00:00
}
2024-08-30 10:13:35 +00:00
void mptWriteMem(void* pStart, int32_t size) {
char* pEnd = (char*)pStart + size - 1;
char* p = (char*)pStart;
while (p <= pEnd) {
*p = 'a' + taosRand() % 26;
p += 4096;
}
}
2024-08-16 10:22:31 +00:00
void mptSimulateAction(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pTask) {
2024-08-08 10:31:33 +00:00
int32_t actId = 0;
bool actDone = false;
2024-11-13 11:19:00 +00:00
int32_t size = 0;
2024-08-30 10:13:35 +00:00
int32_t osize = 0, nsize = 0;
2024-08-02 08:08:19 +00:00
2024-08-08 10:31:33 +00:00
while (!actDone) {
2024-08-16 10:22:31 +00:00
actId = taosRand() % 10;
2024-11-13 11:19:00 +00:00
size = (taosRand() % 10) ? (taosRand() % (mptCtrl.maxSingleAllocSize / 100)) : (taosRand() % mptCtrl.maxSingleAllocSize);
2024-08-08 10:31:33 +00:00
switch (actId) {
case 0: { // malloc
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
}
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx].p = mptMemoryMalloc(size);
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memMalloc.exec++;
pTask->stat.bytes.memMalloc.exec+=size;
pTask->stat.times.memMalloc.fail++;
2024-08-16 10:22:31 +00:00
pTask->stat.bytes.memMalloc.fail+=size;
uError("JOB:0x%x TASK:0x%x mpMalloc %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
pTask->stat.times.memMalloc.exec++;
pTask->stat.bytes.memMalloc.exec+=nsize;
pTask->stat.bytes.memMalloc.succ+=nsize;
pTask->stat.times.memMalloc.succ++;
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
2024-08-08 10:31:33 +00:00
pTask->memIdx++;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
2024-08-02 08:08:19 +00:00
}
2024-08-08 10:31:33 +00:00
case 1: { // calloc
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
2024-08-02 08:08:19 +00:00
}
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx].p = mptMemoryCalloc(1, size);
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memCalloc.exec++;
pTask->stat.bytes.memCalloc.exec+=size;
pTask->stat.times.memCalloc.fail++;
2024-08-16 10:22:31 +00:00
pTask->stat.bytes.memCalloc.fail+=size;
uError("JOB:0x%x TASK:0x%x mpCalloc %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
pTask->stat.times.memCalloc.exec++;
pTask->stat.bytes.memCalloc.exec+=nsize;
pTask->stat.times.memCalloc.succ++;
pTask->stat.bytes.memCalloc.succ+=nsize;
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
2024-08-08 10:31:33 +00:00
pTask->memIdx++;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
2024-08-02 08:08:19 +00:00
}
2024-08-08 10:31:33 +00:00
case 2:{ // new realloc
2024-08-30 10:13:35 +00:00
break;
2024-08-08 10:31:33 +00:00
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
}
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx].p = mptMemoryRealloc(NULL, size);
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memRealloc.exec++;
pTask->stat.bytes.memRealloc.exec+=size;
pTask->stat.times.memRealloc.fail++;
2024-08-16 10:22:31 +00:00
pTask->stat.bytes.memRealloc.fail+=size;
uError("JOB:0x%x TASK:0x%x new mpRealloc %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
pTask->stat.times.memRealloc.exec++;
pTask->stat.bytes.memRealloc.exec+=nsize;
pTask->stat.bytes.memRealloc.succ+=nsize;
pTask->stat.times.memRealloc.succ++;
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
2024-08-08 10:31:33 +00:00
pTask->memIdx++;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
2024-08-02 08:08:19 +00:00
}
2024-08-08 10:31:33 +00:00
case 3:{ // real realloc
2024-08-30 10:13:35 +00:00
break;
2024-08-08 10:31:33 +00:00
if (pTask->memIdx <= 0) {
break;
}
2024-08-07 11:22:01 +00:00
2024-08-08 10:31:33 +00:00
assert(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-30 10:13:35 +00:00
osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-16 10:22:31 +00:00
size++;
pTask->pMemList[pTask->memIdx - 1].p = mptMemoryRealloc(pTask->pMemList[pTask->memIdx - 1].p, size);
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx - 1].p) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memRealloc.exec++;
pTask->stat.bytes.memRealloc.exec+=size;
pTask->stat.bytes.memRealloc.origExec+=osize;
pTask->stat.times.memRealloc.fail++;
2024-08-16 10:22:31 +00:00
pTask->stat.bytes.memRealloc.fail+=size;
2024-11-12 00:42:54 +00:00
pTask->stat.times.memFree.exec++;
pTask->stat.bytes.memFree.exec+=osize;
pTask->stat.times.memFree.succ++;
pTask->stat.bytes.memFree.succ+=osize;
2024-08-16 10:22:31 +00:00
uError("JOB:0x%x TASK:0x%x real mpRealloc %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
pTask->memIdx--;
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p);
pTask->stat.times.memRealloc.exec++;
pTask->stat.bytes.memRealloc.exec+=nsize;
pTask->stat.bytes.memRealloc.origExec+=osize;
pTask->stat.bytes.memRealloc.origSucc+=osize;
pTask->stat.times.memRealloc.succ++;
pTask->stat.bytes.memRealloc.succ+=nsize;
mptWriteMem(pTask->pMemList[pTask->memIdx - 1].p, size);
2024-08-08 10:31:33 +00:00
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
case 4:{ // realloc free
if (pTask->memIdx <= 0) {
break;
}
2024-08-02 08:08:19 +00:00
2024-08-08 10:31:33 +00:00
assert(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-30 10:13:35 +00:00
osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx - 1].p = mptMemoryRealloc(pTask->pMemList[pTask->memIdx - 1].p, 0);
2024-11-12 00:42:54 +00:00
pTask->stat.times.memFree.exec++;
pTask->stat.bytes.memFree.exec+=osize;
2024-08-16 10:22:31 +00:00
assert(NULL == pTask->pMemList[pTask->memIdx - 1].p);
2024-11-12 00:42:54 +00:00
pTask->stat.times.memFree.succ++;
pTask->stat.bytes.memFree.succ+=osize;
2024-08-16 10:22:31 +00:00
2024-08-08 10:31:33 +00:00
pTask->memIdx--;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
case 5:{ // strdup
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
}
2024-08-02 08:08:19 +00:00
2024-08-16 10:22:31 +00:00
size /= 10;
2024-08-08 10:31:33 +00:00
mptCtrl.pSrcString[size] = 0;
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx].p = mptStrdup(mptCtrl.pSrcString);
2024-08-08 10:31:33 +00:00
mptCtrl.pSrcString[size] = 'W';
2024-08-30 10:13:35 +00:00
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-11-06 11:26:14 +00:00
pTask->stat.times.memStrdup.exec++;
pTask->stat.bytes.memStrdup.exec+=size + 1;
pTask->stat.times.memStrdup.fail++;
pTask->stat.bytes.memStrdup.fail+=size + 1;
2024-08-16 10:22:31 +00:00
uError("JOB:0x%x TASK:0x%x mpStrdup %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
2024-11-06 11:26:14 +00:00
pTask->stat.times.memStrdup.exec++;
pTask->stat.bytes.memStrdup.exec+= nsize;
2024-08-30 10:13:35 +00:00
2024-11-06 11:26:14 +00:00
pTask->stat.times.memStrdup.succ++;
pTask->stat.bytes.memStrdup.succ+=nsize;
2024-08-30 10:13:35 +00:00
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
2024-08-08 10:31:33 +00:00
pTask->memIdx++;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
case 6:{ // strndup
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
}
2024-08-02 08:08:19 +00:00
2024-08-16 10:22:31 +00:00
size /= 10;
2024-08-30 10:13:35 +00:00
assert(strlen(mptCtrl.pSrcString) > size);
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx].p = mptStrndup(mptCtrl.pSrcString, size);
2024-08-30 10:13:35 +00:00
2024-08-08 10:31:33 +00:00
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-11-06 11:26:14 +00:00
pTask->stat.times.memStrndup.exec++;
pTask->stat.bytes.memStrndup.exec+=size + 1;
pTask->stat.times.memStrndup.fail++;
pTask->stat.bytes.memStrndup.fail+=size + 1;
2024-08-16 10:22:31 +00:00
uError("JOB:0x%x TASK:0x%x mpStrndup %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
assert(strlen((char*)pTask->pMemList[pTask->memIdx].p) == size);
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
2024-11-06 11:26:14 +00:00
pTask->stat.times.memStrndup.exec++;
pTask->stat.bytes.memStrndup.exec+=nsize;
pTask->stat.times.memStrndup.succ++;
pTask->stat.bytes.memStrndup.succ+=nsize;
2024-08-30 10:13:35 +00:00
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
2024-08-08 10:31:33 +00:00
pTask->memIdx++;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
case 7:{ // free
if (pTask->memIdx <= 0) {
break;
}
2024-08-02 08:08:19 +00:00
2024-08-08 10:31:33 +00:00
assert(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-30 10:13:35 +00:00
osize = mptMemorySize(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-16 10:22:31 +00:00
mptMemoryFree(pTask->pMemList[pTask->memIdx - 1].p);
2024-08-30 10:13:35 +00:00
pTask->stat.times.memFree.exec++;
pTask->stat.times.memFree.succ++;
pTask->stat.bytes.memFree.exec+=osize;
pTask->stat.bytes.memFree.succ+=osize;
2024-08-16 10:22:31 +00:00
pTask->pMemList[pTask->memIdx - 1].p = NULL;
2024-08-08 10:31:33 +00:00
pTask->memIdx--;
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
case 8:{ // trim
2024-08-30 10:13:35 +00:00
bool trimed = false;
int32_t code = mptMemoryTrim(0, &trimed);
pTask->stat.times.memTrim.exec++;
if (code) {
pTask->stat.times.memTrim.fail++;
} else {
pTask->stat.times.memTrim.succ++;
if (trimed) {
pTask->stat.bytes.memTrim.succ++;
}
}
2024-08-16 10:22:31 +00:00
pTask->lastAct = actId;
actDone = true;
break;
}
case 9: { // malloc_align
if (pTask->memIdx >= MPT_MAX_MEM_ACT_TIMES) {
break;
}
pTask->pMemList[pTask->memIdx].p = mptMemoryMallocAlign(8, size);
if (NULL == pTask->pMemList[pTask->memIdx].p) {
2024-08-30 10:13:35 +00:00
pTask->stat.times.memMalloc.exec++;
pTask->stat.bytes.memMalloc.exec+=size;
pTask->stat.times.memMalloc.fail++;
pTask->stat.bytes.memMalloc.fail+=size;
2024-08-16 10:22:31 +00:00
uError("JOB:0x%x TASK:0x%x mpMallocAlign %d failed, terrno:0x%x", pJobCtx->jobId, pTask->taskId, size, terrno);
return;
}
2024-08-30 10:13:35 +00:00
nsize = mptMemorySize(pTask->pMemList[pTask->memIdx].p);
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
mptWriteMem(pTask->pMemList[pTask->memIdx].p, size);
pTask->stat.times.memMalloc.exec++;
pTask->stat.bytes.memMalloc.exec+=nsize;
2024-08-16 10:22:31 +00:00
2024-08-30 10:13:35 +00:00
pTask->stat.times.memMalloc.succ++;
pTask->stat.bytes.memMalloc.succ+=nsize;
2024-08-16 10:22:31 +00:00
pTask->memIdx++;
pTask->lastAct = actId;
2024-08-08 10:31:33 +00:00
actDone = true;
break;
}
default:
assert(0);
break;
}
2024-08-02 08:08:19 +00:00
}
}
2024-11-14 09:38:20 +00:00
void mptSimulateTask(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pTask, int32_t actTimes) {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x will start total %d actions", pJobCtx->jobId, pTask->taskId, actTimes);
2024-08-08 10:31:33 +00:00
for (int32_t i = 0; i < actTimes; ++i) {
if (atomic_load_8(&pJobCtx->pJob->retired)) {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x stop running cause of job already retired", pJobCtx->jobId, pTask->taskId);
2024-08-08 10:31:33 +00:00
return;
}
2024-11-14 09:38:20 +00:00
//MPT_PRINTF("\tTASK:0x%x will start %d:%d actions\n", pTask->taskId, i, actTimes);
2024-08-08 10:31:33 +00:00
2024-08-16 10:22:31 +00:00
mptSimulateAction(pJobCtx, pTask);
2024-08-02 08:08:19 +00:00
}
}
2024-08-08 10:31:33 +00:00
void mptSimulateOutTask(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pTask) {
if (atomic_load_8(&pJobCtx->pJob->retired)) {
return;
2024-08-07 11:22:01 +00:00
}
2024-08-08 10:31:33 +00:00
if (taosRand() % 10 > 0) {
return;
}
if (pTask->npMemIdx >= MPT_MAX_MEM_ACT_TIMES) {
return;
}
2024-08-16 10:22:31 +00:00
pTask->npMemList[pTask->npMemIdx].size = taosRand() % mptCtrl.maxSingleAllocSize;
pTask->npMemList[pTask->npMemIdx].p = taosMemMalloc(pTask->npMemList[pTask->npMemIdx].size);
if (NULL == pTask->npMemList[pTask->npMemIdx].p) {
uError("JOB:0x%x TASK:0x%x out malloc %" PRId64 " failed", pJobCtx->jobId, pTask->taskId, pTask->npMemList[pTask->npMemIdx].size);
pTask->npMemList[pTask->npMemIdx].size = 0;
return;
}
uDebug("JOB:0x%x TASK:0x%x out malloced, size:%" PRId64 ", mIdx:%d", pJobCtx->jobId, pTask->taskId, pTask->npMemList[pTask->npMemIdx].size, pTask->npMemIdx);
2024-08-07 11:22:01 +00:00
2024-08-16 10:22:31 +00:00
pTask->npMemIdx++;
}
2024-08-07 11:22:01 +00:00
2024-11-14 09:38:20 +00:00
void mptTaskRun(SMPTestJobCtx* pJobCtx, SMPTestTaskCtx* pCtx, int32_t idx, int32_t actTimes) {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x start running", pJobCtx->jobId, pCtx->taskId);
2024-08-08 10:31:33 +00:00
if (atomic_load_8(&pJobCtx->pJob->retired)) {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x stop running cause of job already retired", pJobCtx->jobId, pCtx->taskId);
2024-08-08 10:31:33 +00:00
return;
}
if (taosWTryLockLatch(&pCtx->taskExecLock)) {
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x stop running cause of task already running", pJobCtx->jobId, pCtx->taskId);
2024-08-08 10:31:33 +00:00
return;
}
2024-08-07 11:22:01 +00:00
2024-08-08 10:31:33 +00:00
atomic_add_fetch_32(&pJobCtx->taskRunningNum, 1);
2024-08-07 11:22:01 +00:00
2024-11-12 00:42:54 +00:00
mptEnableMemoryPoolUsage(gMemPoolHandle, pJobCtx->pSessions[idx]);
2024-11-14 09:38:20 +00:00
mptSimulateTask(pJobCtx, pCtx, actTimes);
mptDisableMemoryPoolUsage();
2024-08-16 10:22:31 +00:00
if (!atomic_load_8(&pJobCtx->pJob->retired)) {
mptSimulateOutTask(pJobCtx, pCtx);
}
2024-08-08 10:31:33 +00:00
taosWUnLockLatch(&pCtx->taskExecLock);
2024-08-07 11:22:01 +00:00
2024-08-08 10:31:33 +00:00
atomic_sub_fetch_32(&pJobCtx->taskRunningNum, 1);
2024-08-16 10:22:31 +00:00
uDebug("JOB:0x%x TASK:0x%x end running", pJobCtx->jobId, pCtx->taskId);
2024-08-07 11:22:01 +00:00
}
void mptInitJobs() {
2024-08-16 10:22:31 +00:00
int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM;
memset(mptCtx.jobCtxs, 0, sizeof(*mptCtx.jobCtxs) * jobNum);
for (int32_t i = 0; i < jobNum; ++i) {
2024-08-07 11:22:01 +00:00
mptInitJob(i);
}
}
2024-08-30 10:13:35 +00:00
void mptCheckPoolUsedSize(int32_t jobNum) {
int64_t usedSize = 0;
bool needEnd = false;
int64_t poolUsedSize = 0;
2024-11-15 09:05:46 +00:00
int32_t sleepTimes = 0;
2024-11-13 11:19:00 +00:00
2024-11-15 09:05:46 +00:00
while (true) {
taosMemPoolGetUsedSizeBegin(gMemPoolHandle, &usedSize, &needEnd);
2024-11-13 11:19:00 +00:00
2024-11-15 09:05:46 +00:00
poolUsedSize = 0;
for (int32_t i = 0; i < jobNum; ++i) {
SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[i];
sleepTimes = 0;
while (taosRTryLockLatch(&pJobCtx->jobExecLock)) {
taosUsleep(1);
sleepTimes++;
if (sleepTimes > 100) {
break;
}
}
2024-08-30 10:13:35 +00:00
2024-11-15 09:05:46 +00:00
if (sleepTimes > 100) {
break;
2024-11-15 02:16:15 +00:00
}
2024-11-15 09:05:46 +00:00
2024-11-15 10:15:50 +00:00
if (NULL == pJobCtx->pJob) {
continue;
}
2024-11-15 09:05:46 +00:00
int64_t jobUsedSize = 0;
for (int32_t m = 0; m < pJobCtx->taskNum; ++m) {
if (!pJobCtx->taskCtxs[m].destoryed) {
SMPStatDetail* pStat = NULL;
int64_t allocSize = 0;
taosMemPoolGetSessionStat(pJobCtx->pSessions[m], &pStat, &allocSize, NULL);
int64_t usedSize = MEMPOOL_GET_USED_SIZE(pStat);
assert(allocSize == usedSize);
assert(0 == memcmp(pStat, &pJobCtx->taskCtxs[m].stat, sizeof(*pStat)));
jobUsedSize += allocSize;
}
}
assert(pJobCtx->pJob->memInfo->allocMemSize == jobUsedSize);
taosRUnLockLatch(&pJobCtx->jobExecLock);
poolUsedSize += jobUsedSize;
2024-08-30 10:13:35 +00:00
}
2024-11-15 09:05:46 +00:00
taosMemPoolGetUsedSizeEnd(gMemPoolHandle);
2024-11-13 11:19:00 +00:00
2024-11-15 09:05:46 +00:00
if (sleepTimes > 100) {
continue;
}
2024-08-30 10:13:35 +00:00
2024-11-15 09:05:46 +00:00
assert(poolUsedSize <= usedSize);
break;
}
2024-08-30 10:13:35 +00:00
}
2024-11-15 09:05:46 +00:00
void* mptRunThreadFunc(void* param) {
2024-08-07 11:22:01 +00:00
SMPTestThread* pThread = (SMPTestThread*)param;
2024-08-16 10:22:31 +00:00
int32_t jobExecTimes = (mptCtrl.jobExecTimes) ? mptCtrl.jobExecTimes : taosRand() % MPT_MAX_JOB_LOOP_TIMES + 1;
2024-08-07 11:22:01 +00:00
2024-08-16 10:22:31 +00:00
for (int32_t n = 0; n < jobExecTimes; ++n) {
2024-11-15 09:05:46 +00:00
mptCtx.jobNum = (mptCtrl.jobNum) ? mptCtrl.jobNum : (taosRand() % MPT_MAX_JOB_NUM + 1);
mptCtx.jobLoop = n;
2024-08-08 10:31:33 +00:00
2024-11-15 09:05:46 +00:00
MPT_PRINTF("Thread %d start the %d:%d job loops - jobNum:%d\n", pThread->idx, n, jobExecTimes, mptCtx.jobNum);
for (int32_t i = 0; i < mptCtx.jobNum; ++i) {
2024-08-16 10:22:31 +00:00
SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[i];
2024-11-15 09:05:46 +00:00
MPT_PRINTF(" Thread %d start to run %d:%d job[%d:0x%" PRIx64 "]\n", pThread->idx, i, mptCtx.jobNum, pJobCtx->jobIdx, pJobCtx->jobId);
2024-08-07 11:22:01 +00:00
2024-08-16 10:22:31 +00:00
if (mptResetJob(pJobCtx)) {
continue;
2024-08-08 10:31:33 +00:00
}
2024-08-16 10:22:31 +00:00
if (taosRTryLockLatch(&pJobCtx->jobExecLock)) {
continue;
}
2024-08-08 10:31:33 +00:00
if (mptCtx.param.randTask) {
2024-11-14 09:38:20 +00:00
int32_t actTimes = mptCtrl.taskActTimes ? mptCtrl.taskActTimes : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_MEM_ACT_TIMES/10)) : (taosRand() % MPT_MAX_MEM_ACT_TIMES));
2024-08-08 10:31:33 +00:00
int32_t taskIdx = taosRand() % pJobCtx->taskNum;
2024-11-14 09:38:20 +00:00
mptTaskRun(pJobCtx, &pJobCtx->taskCtxs[taskIdx], taskIdx, actTimes);
2024-08-08 10:31:33 +00:00
continue;
}
for (int32_t m = 0; m < pJobCtx->taskNum; ++m) {
if (atomic_load_8(&pJobCtx->pJob->retired)) {
break;
}
2024-11-14 09:38:20 +00:00
2024-11-15 09:05:46 +00:00
if (pJobCtx->taskCtxs[m].destoryed) {
continue;
}
2024-11-14 09:38:20 +00:00
int32_t actTimes = mptCtrl.taskActTimes ? mptCtrl.taskActTimes : ((taosRand() % 10) ? (taosRand() % (MPT_MAX_MEM_ACT_TIMES/10)) : (taosRand() % MPT_MAX_MEM_ACT_TIMES));
MPT_PRINTF("Thread %d start to run %d:%d task\n", pThread->idx, m, pJobCtx->taskNum);
mptTaskRun(pJobCtx, &pJobCtx->taskCtxs[m], m, actTimes);
2024-08-08 10:31:33 +00:00
}
2024-08-16 10:22:31 +00:00
taosRUnLockLatch(&pJobCtx->jobExecLock);
MPT_PRINTF(" Thread %d end %dth JOB 0x%x exec, retired:%d\n", pThread->idx, pJobCtx->jobIdx, pJobCtx->jobId, pJobCtx->pJob->retired);
mptResetJob(pJobCtx);
2024-08-07 11:22:01 +00:00
}
2024-08-16 10:22:31 +00:00
MPT_PRINTF("Thread %d finish the %dth job loops\n", pThread->idx, n);
2024-08-30 10:13:35 +00:00
2024-11-15 09:05:46 +00:00
mptCheckPoolUsedSize(mptCtx.jobNum);
2024-08-07 11:22:01 +00:00
}
return NULL;
}
2024-11-15 09:05:46 +00:00
void* mptDropThreadFunc(void* param) {
int32_t jobIdx = 0, taskIdx = 0, code = 0;
uint64_t taskId = 0;
while (!atomic_load_8(&mptCtx.testDone)) {
taosMsleep(200);
jobIdx = taosRand() % mptCtx.jobNum;
SMPTestJobCtx* pJobCtx = &mptCtx.jobCtxs[jobIdx];
taosWLockLatch(&pJobCtx->jobExecLock);
if (NULL == pJobCtx->pJob || pJobCtx->pJob->destroyed) {
taosWUnLockLatch(&pJobCtx->jobExecLock);
continue;
}
if (taosRand() % 20) {
taskIdx = taosRand() % pJobCtx->taskNum;
if (pJobCtx->taskCtxs[taskIdx].destoryed) {
taosWUnLockLatch(&pJobCtx->jobExecLock);
continue;
}
taskId = pJobCtx->taskCtxs[taskIdx].taskId;
mptDestroyTask(pJobCtx, taskIdx);
MPT_PRINTF("Drop Thread destroy task %d:0x%" PRIx64 " in job %d:%" PRIx64 "\n", taskIdx, taskId, jobIdx, pJobCtx->jobId);
taosWUnLockLatch(&pJobCtx->jobExecLock);
} else {
taosWUnLockLatch(&pJobCtx->jobExecLock);
code = mptDestroyJob(pJobCtx, false);
if (0 == code) {
MPT_PRINTF("Drop Thread destroy job %d:%" PRIx64 "\n", jobIdx, pJobCtx->jobId);
}
}
}
return NULL;
}
void mptStartRunThread(int32_t threadIdx) {
TdThreadAttr thattr;
ASSERT_EQ(0, taosThreadAttrInit(&thattr));
ASSERT_EQ(0, taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE));
2024-08-16 10:22:31 +00:00
mptCtx.threadCtxs[threadIdx].idx = threadIdx;
2024-11-15 09:05:46 +00:00
ASSERT_EQ(0, taosThreadCreate(&mptCtx.threadCtxs[threadIdx].threadFp, &thattr, mptRunThreadFunc, &mptCtx.threadCtxs[threadIdx]));
ASSERT_EQ(0, taosThreadAttrDestroy(&thattr));
2024-11-15 09:05:46 +00:00
}
2024-11-15 09:05:46 +00:00
void mptStartDropThread() {
TdThreadAttr thattr;
ASSERT_EQ(0, taosThreadAttrInit(&thattr));
ASSERT_EQ(0, taosThreadAttrSetDetachState(&thattr, PTHREAD_CREATE_JOINABLE));
ASSERT_EQ(0, taosThreadCreate(&mptCtx.dropThreadFp, &thattr, mptDropThreadFunc, NULL));
ASSERT_EQ(0, taosThreadAttrDestroy(&thattr));
}
2024-11-15 09:05:46 +00:00
2024-08-08 10:31:33 +00:00
void mptDestroyJobs() {
2024-08-16 10:22:31 +00:00
int32_t jobNum = mptCtrl.jobNum ? mptCtrl.jobNum : MPT_MAX_JOB_NUM;
for (int32_t i = 0; i < jobNum; ++i) {
2024-08-08 10:31:33 +00:00
mptDestroyJob(&mptCtx.jobCtxs[i], false);
}
}
2024-08-16 10:22:31 +00:00
void mptRunCase(SMPTestParam* param, int32_t times) {
MPT_PRINTF("\t case start the %dth running\n", times);
2024-11-15 09:05:46 +00:00
mptCtx.caseLoop = times;
2024-08-07 11:22:01 +00:00
memcpy(&mptCtx.param, param, sizeof(SMPTestParam));
2024-11-15 09:05:46 +00:00
atomic_store_8(&mptCtx.testDone, 0);
2024-08-07 11:22:01 +00:00
mptInitPool();
2024-08-07 11:22:01 +00:00
mptInitJobs();
for (int32_t i = 0; i < mptCtx.param.threadNum; ++i) {
2024-11-15 09:05:46 +00:00
mptStartRunThread(i);
2024-08-07 11:22:01 +00:00
}
2024-08-08 10:31:33 +00:00
2024-11-15 09:05:46 +00:00
mptStartDropThread();
2024-08-08 10:31:33 +00:00
for (int32_t i = 0; i < mptCtx.param.threadNum; ++i) {
(void)taosThreadJoin(mptCtx.threadCtxs[i].threadFp, NULL);
}
2024-11-15 09:05:46 +00:00
atomic_store_8(&mptCtx.testDone, 1);
(void)taosThreadJoin(mptCtx.dropThreadFp, NULL);
2024-08-08 10:31:33 +00:00
mptDestroyJobs();
2024-08-16 10:22:31 +00:00
2024-11-15 09:05:46 +00:00
taosMemPoolClose(gMemPoolHandle);
gMemPoolHandle = NULL;
2024-08-16 10:22:31 +00:00
MPT_PRINTF("\t case end the %dth running\n", times);
}
void mptPrintTestBeginInfo(char* caseName, SMPTestParam* param) {
MPT_PRINTF("Case [%s] begins:\n", caseName);
MPT_PRINTF("\t case loop times: %d\n", mptCtrl.caseLoopTimes);
MPT_PRINTF("\t task max act times: %d\n", mptCtrl.taskActTimes ? mptCtrl.taskActTimes : MPT_MAX_MEM_ACT_TIMES);
MPT_PRINTF("\t max single alloc size: %" PRId64 "\n", mptCtrl.maxSingleAllocSize);
MPT_PRINTF("\t job quota size: %" PRId64 "\n", param->jobQuota);
2024-11-06 11:26:14 +00:00
MPT_PRINTF("\t reserve mode: %d\n", param->reserveMode);
2024-11-12 00:42:54 +00:00
//MPT_PRINTF("\t upper limit size: %" PRId64 "\n", param->upperLimitSize);
2024-08-16 10:22:31 +00:00
MPT_PRINTF("\t test thread num: %d\n", param->threadNum);
MPT_PRINTF("\t random exec task: %d\n", param->randTask);
}
2024-08-02 08:08:19 +00:00
} // namespace
#if 1
2024-08-30 10:13:35 +00:00
2024-11-12 00:42:54 +00:00
#if 0
2024-08-30 10:13:35 +00:00
TEST(FuncTest, SysMemoryPerfTest) {
char* caseName = "FuncTest:SingleThreadTest";
int32_t code = 0;
int64_t msize = 1048576UL*10240;
char* p = (char*)taosMemMalloc(msize);
int64_t st = taosGetTimestampUs();
memset(p, 0, msize);
int64_t totalUs = taosGetTimestampUs() - st;
2024-11-12 00:42:54 +00:00
printf("memset %" PRId64 " used time:%" PRId64 "us, speed:%dMB/ms\n", msize, totalUs, msize/1048576UL/(totalUs/1000UL));
2024-08-30 10:13:35 +00:00
int64_t freeSize = 0;
int32_t loopTimes = 1000000;
st = taosGetTimestampUs();
int64_t lt = st;
for (int32_t i = 0; i < loopTimes; ++i) {
code = taosGetSysAvailMemory(&freeSize);
assert(0 == code);
2024-11-12 00:42:54 +00:00
taosMsleep(5);
2024-08-30 10:13:35 +00:00
}
totalUs = taosGetTimestampUs() - st;
printf("%d times getSysMemory total time:%" PRId64 "us, avg:%dus\n", loopTimes, totalUs, totalUs/loopTimes);
}
#endif
2024-11-06 11:26:14 +00:00
#if 1
2024-08-16 10:22:31 +00:00
TEST(FuncTest, SingleThreadTest) {
2024-08-02 08:08:19 +00:00
char* caseName = "FuncTest:SingleThreadTest";
2024-08-08 10:31:33 +00:00
SMPTestParam param = {0};
2024-11-06 11:26:14 +00:00
param.reserveMode = true;
2024-08-16 10:22:31 +00:00
param.threadNum = 1;
mptPrintTestBeginInfo(caseName, &param);
2024-08-02 08:08:19 +00:00
2024-08-08 10:31:33 +00:00
for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) {
2024-08-16 10:22:31 +00:00
mptRunCase(&param, i);
2024-08-08 10:31:33 +00:00
}
2024-08-02 08:08:19 +00:00
}
#endif
2024-08-08 10:31:33 +00:00
#if 0
2024-08-16 10:22:31 +00:00
TEST(FuncTest, MultiThreadsTest) {
char* caseName = "FuncTest:MultiThreadsTest";
2024-08-08 10:31:33 +00:00
SMPTestParam param = {0};
2024-08-07 11:22:01 +00:00
2024-08-08 10:31:33 +00:00
for (int32_t i = 0; i < mptCtrl.caseLoopTimes; ++i) {
mptRunCase(&param);
}
2024-08-07 11:22:01 +00:00
}
#endif
2024-08-02 08:08:19 +00:00
#endif
int main(int argc, char** argv) {
taosSeedRand(taosGetTimestampSec());
mptInit();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#pragma GCC diagnosti