37 # include <sys/mman.h>
42 #define __NC_MEMMAN_USE_MALLOC_HOOK 1
45 #define __NC_MEMMAN_DEBUG 0
46 #define __NC_MEMMAN_ALLPTR_COUNT 0
50 #define __NC_MEMMAN_PERTHREAD_STAT 0
52 #if __NC_MEMMAN_PERTHREAD_STAT
53 #define __NC_MEMMAN_PERTHREAD_STAT_ARG(x) x
55 #define __NC_MEMMAN_PERTHREAD_STAT_ARG(x)
92 #if __NC_MEMMAN_NEWALLOC
93 #if __NC_MEMMAN_USEREALPTR
121 #if !__NC_MEMMAN_USE_STD_MALLOC
147 #if !__NC_MEMMAN_USE_STD_MALLOC
154 #if !__NC_MEMMAN_PERTHREAD_STAT
165 #if __NC_MEMMAN_ALLPTR_COUNT
169 #if __NC_MEMMAN_DEBUG
170 static Uint8 s_fdMemManStamp = 0xFEEDFEEDFEEDFEED;
171 static const Uint8 s_MaxAllPools = 200;
178 static void s_VerifyUnavailable(
void* ptr,
Uint2 size_idx)
180 for (
Uint8 p = 0; p < s_MaxAllPools; ++p) {
193 for (
void* next_block = page->
free_list; next_block; next_block = *(
void**)next_block) {
194 if (next_block == ptr) {
202 static const Uint8 s_MaxAllPtr = 20000;
206 static void s_GivePtr(
void* ptr,
Uint2 size_idx)
209 void** p = s_AllPtr + (size_idx * s_MaxAllPtr);
210 for(
Uint8 i = 0;
i < s_MaxAllPtr; ++
i, ++p) {
219 static void s_TakePtr(
void* ptr,
Uint2 size_idx)
222 void** p = s_AllPtr + (size_idx * s_MaxAllPtr);
223 for(
Uint8 i = 0;
i < s_MaxAllPtr; ++
i, ++p) {
238 { 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 96, 112, 128, 152, 176, 208, 248,
239 296, 352, 416, 496, 592, 704, 840, 1008, 1208, 1448, 1736, 2080, 2496,
277 Uint4 sz_ind = 0, sz = 0, lookup_ind = 0;
285 #if __NC_MEMMAN_DEBUG
302 #if __NC_MEMMAN_USE_STD_MALLOC
319 void* ptr = mmap(
NULL,
size, PROT_READ | PROT_WRITE,
320 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
321 if (ptr == MAP_FAILED) {
322 static bool reentry =
false;
327 SRV_FATAL(
"s_DoMmap failed when requesting "
328 <<
size <<
" bytes, errno: " << errno
342 if (munmap(ptr,
size) != 0) {
343 SRV_LOG(SoftFatal,
"Fatal error: " <<
"s_DoUnmap failed, errno: " << errno
349 #if __NC_MEMMAN_NEWALLOC
354 #if __NC_MEMMAN_USEREALPTR
356 return (munmap(ptr,
size) == 0);
367 size_t aligned_ptr = ptr, new_size =
size;
374 if (aligned_ptr == ptr) {
378 if ((ptr + new_size > aligned_ptr) && (ptr + new_size - aligned_ptr >=
size)) {
379 if (
s_TryUnmap((
void*)ptr, aligned_ptr - ptr)) {
380 new_size -= (aligned_ptr - ptr);
389 #if __NC_MEMMAN_USEREALPTR
390 page->real_ptr = (
void*)ptr;
405 #if __NC_MEMMAN_USEREALPTR
406 page->real_ptr = page;
421 #if __NC_MEMMAN_USEREALPTR
435 if (aligned_ptr == ptr) {
440 s_DoUnmap((
void*)ptr, aligned_ptr - ptr);
444 return (
void*)aligned_ptr;
484 return list_head->
next_page == list_head;
498 #if __NC_MEMMAN_DEBUG
512 #if __NC_MEMMAN_DEBUG
564 #if !__NC_MEMMAN_NEWALLOC
569 #if __NC_MEMMAN_PERTHREAD_STAT
574 #if __NC_MEMMAN_ALLPTR_COUNT
581 #if __NC_MEMMAN_DEBUG
582 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
588 *(
void**)block =
next;
592 *(
void**)block =
NULL;
604 void*
result = next_block;
605 next_block = *(
void**)next_block;
607 #if __NC_MEMMAN_DEBUG
612 for (; to_fill != 0; --to_fill) {
614 next_block = *(
void**)next_block;
619 #if __NC_MEMMAN_DEBUG
620 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
624 memcpy(pool->
blocks[
cnt], &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
626 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
634 #if __NC_MEMMAN_DEBUG
635 memcpy(
result, &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
636 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
675 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
680 #if __NC_MEMMAN_DEBUG
681 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
688 #if __NC_MEMMAN_PERTHREAD_STAT
693 #if __NC_MEMMAN_ALLPTR_COUNT
747 memcpy(pool->
blocks, &glob_pool.
blocks[1], cnt_copy *
sizeof(
void*));
748 #if __NC_MEMMAN_DEBUG
750 memcpy(pool->
blocks[
cnt], &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
810 to_copy *
sizeof(
void*));
859 #if __NC_MEMMAN_PERTHREAD_STAT
868 #if __NC_MEMMAN_DEBUG
869 memcpy(&page[1], &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
870 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
882 #if __NC_MEMMAN_PERTHREAD_STAT
919 #if __NC_MEMMAN_DEBUG
920 lock_AllPools.
Lock();
927 #if __NC_MEMMAN_PERTHREAD_STAT
937 #if __NC_MEMMAN_ALLPTR_COUNT
940 #if __NC_MEMMAN_DEBUG
941 s_GivePtr(ptr,size_idx);
942 if (
s_FreePages[size_idx].lists[0].list_head.block_size != 0 &&
952 #if __NC_MEMMAN_DEBUG
953 if (memcmp(ptr, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) != 0) {
956 memset(ptr, 0,
sizeof(s_fdMemManStamp));
958 #if __NC_MEMMAN_DEBUG
967 #if !__NC_MEMMAN_USE_MALLOC_HOOK
976 #if __NC_MEMMAN_DEBUG
977 lock_AllPools.
Lock();
984 #if __NC_MEMMAN_PERTHREAD_STAT
989 #if __NC_MEMMAN_ALLPTR_COUNT
992 #if __NC_MEMMAN_DEBUG
993 s_TakePtr(ptr,size_idx);
994 if (memcmp(ptr, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
997 memcpy(ptr, &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
998 s_VerifyUnavailable(ptr, size_idx);
1008 #if __NC_MEMMAN_DEBUG
1009 if (memcmp(ptr, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
1012 memcpy(ptr, &s_fdMemManStamp,
sizeof(s_fdMemManStamp));
1013 if (page->
free_list && memcmp(page->
free_list, &s_fdMemManStamp,
sizeof(s_fdMemManStamp)) == 0) {
1019 #if __NC_MEMMAN_DEBUG
1073 #if !__NC_MEMMAN_USE_MALLOC_HOOK
1082 #if __NC_MEMMAN_USE_STD_MALLOC
1086 if (
thr->thread_num == 0) {
1092 thr->mm_pool = pool_set;
1094 #if __NC_MEMMAN_DEBUG
1095 if (
thr->thread_num < s_MaxAllPools) {
1096 s_AllMemPoolsSet[
thr->thread_num] =
thr->mm_pool;
1102 thr->stat->SetMMStat(&
thr->mm_pool->stat);
1108 #if !__NC_MEMMAN_USE_STD_MALLOC
1113 #if !__NC_MEMMAN_USE_STD_MALLOC
1117 #if __NC_TASKS_MONITOR
1118 m_TaskName =
"CMMFlusher";
1143 if (cnt_blocks == 0) {
1148 memcpy(
buffer, pool.
blocks, cnt_blocks *
sizeof(
void*));
1164 #if __NC_MEMMAN_PERTHREAD_STAT
1165 Uint8 total_data = 0;
1182 Uint8 total_data = 0;
1222 #if __NC_MEMMAN_PERTHREAD_STAT
1223 Uint8 total_data = 0;
1233 Uint8 total_data = 0;
1266 #if __NC_MEMMAN_PERTHREAD_STAT
1326 if (was_blocks == is_blocks) {
1329 else if (is_blocks > was_blocks) {
1330 Int8 diff = is_blocks - was_blocks;
1334 Int8 diff = was_blocks - is_blocks;
1346 if (start_blocks[
i] == 0 && end_blocks[
i] == 0)
1349 proxy << low_size <<
"-" <<
size <<
": ";
1350 if (start_blocks[
i] == end_blocks[
i]) {
1351 proxy <<
"unchanged ("
1370 proxy <<
"Data memory state by size:" << endl;
1373 proxy <<
"Big size: ";
1377 proxy <<
"unchanged ("
1401 proxy << endl <<
"Sys memory state by size:" << endl;
1404 proxy << endl <<
"Memory flow by size:" << endl;
1411 proxy << low_size <<
"-" <<
size <<
": ";
1426 low_size =
size + 1;
1429 proxy <<
"Big size: ";
1447 #if !__NC_MEMMAN_USE_STD_MALLOC
1449 <<
"Data memory state - "
1454 proxy <<
"System memory state - "
1467 string is(
"\": "), iss(
"\": \""), eol(
",\n\""), qt(
"\"");
1469 #if __NC_MEMMAN_USE_STD_MALLOC
1470 #if defined(NETCACHE_MEMORY_MAN_TCM)
1479 #if __NC_MEMMAN_USE_STD_MALLOC
1490 #if __NC_MEMMAN_ALLPTR_COUNT
1514 #if !__NC_MEMMAN_USE_STD_MALLOC
1518 #
if defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ANY_CLANG)
1526 operator delete (
void* ptr)
throw ()
1533 #
if defined(NCBI_COMPILER_GCC) || defined(NCBI_COMPILER_ANY_CLANG)
1541 operator delete[] (
void* ptr)
throw ()
1549 #if __NC_MEMMAN_USE_MALLOC_HOOK
1551 #ifndef __MALLOC_HOOK_VOLATILE
1552 # define __MALLOC_HOOK_VOLATILE
1556 s_MallocHook(
size_t size,
const void* caller)
1562 s_ReallocHook(
void* mem_ptr,
size_t size,
const void* caller)
1568 s_FreeHook(
void* mem_ptr,
const void* caller)
1574 s_InitMallocHook(
void)
1576 __malloc_hook = &s_MallocHook;
1577 __realloc_hook = &s_ReallocHook;
1578 __free_hook = &s_FreeHook;
1581 void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void) = &s_InitMallocHook;
1592 void* realloc(
void* mem_ptr,
size_t size)
1597 void free(
void* mem_ptr)
1606 size_t malloc_usable_size(
void* mem_ptr)
virtual ~CMMFlusher(void)
virtual void ExecuteSlice(TSrvThreadNum thr_num)
This is the main method to do all work this task should do.
Mutex created to have minimum possible size (its size is 4 bytes) and to sleep using kernel capabilit...
void Unlock(void)
Unlock the mutex.
void Lock(void)
Lock the mutex.
Class used in all diagnostic logging.
CSrvDiagMsg & PrintExtra(void)
Starts "extra" message.
CSrvDiagMsg & PrintParam(CTempString name, CTempString value)
Adds parameter to "request-start" or "extra" message.
void Flush(void)
Finishes current message and prepare to start new one.
Stream-like class to help unify printing some text messages to diagnostics and to any socket.
Task controlling a socket.
CSrvSocketTask & WriteText(CTempString message)
Write text into socket.
CSrvSocketTask & WriteNumber(NumType num)
Write number into socket as string, i.e.
T GetAverage(void) const
Get average of all values in the set.
void Initialize(void)
Initialize all data members.
void AddValue(T value)
Add next value into the set.
void AddValues(const CSrvStatTerm< T > &other)
Add all values from another set.
T GetMaximum(void) const
Get maximum value in the set.
Main working entity in TaskServer.
void RunAfter(Uint4 delay_sec)
This call is basically equivalent to SetRunnable() but with guarantee that task will be scheduled for...
static bool IsInShutdown(void)
Checks if TaskServer received request to shutdown.
static DLIST_TYPE *DLIST_NAME() next(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
uint8_t Uint1
1-byte (8-bit) unsigned integer
uint32_t Uint4
4-byte (32-bit) unsigned integer
uint16_t Uint2
2-byte (16-bit) unsigned integer
int64_t Int8
8-byte (64-bit) signed integer
uint64_t Uint8
8-byte (64-bit) unsigned integer
#define END_NCBI_SCOPE
End previously defined NCBI scope.
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
static string UInt8ToString_DataSize(Uint8 value, TNumToStringFlags flags=0, unsigned int max_digits=3)
Convert UInt8 to string using "software" qualifiers.
where boath are integers</td > n< td ></td > n</tr > n< tr > n< td > tse</td > n< td > optional</td > n< td > String</td > n< td class=\"description\"> TSE option controls what blob is smart and slim</td> n<td> orig</td> n</tr> n<tr> n<td> last_modified</td> n<td> optional</td> n<td> Integer</td> n<td class=\"description\"> The blob last modification If provided then the exact match will be requested with n the Cassandra storage corresponding field value</td> n<td> Positive integer Not provided means that the most recent match will be selected</td> n<td></td> n</tr> n<tr> n<td> use_cache</td> n<td> optional</td> n<td> String</td> n<td class=\"description\"> The option controls if the Cassandra LMDB cache and or database should be used It n affects the seq id resolution step and the blob properties lookup step The following n options are available
if(yy_accept[yy_current_state])
static SMMFreePageGrades s_FreePages[kMMCntBlockSizes]
static Uint2 kMMSizeIndexes[kMMMaxBlockSize/8+1]
static void s_InitPoolsSet(SMMMemPoolsSet *pool_set)
static const size_t kMMAllocPageMask
static bool s_TryUnmap(void *ptr, size_t size)
static void s_PutToPool(SMMBlocksPool *pool, void *ptr, SMMStat *stat)
void AssignThreadMemMgr(SSrvThread *thr)
static CMMFlusher * s_Flusher
static void * s_GetFromGlobal(Uint2 size_idx, SMMStat *stat)
static SMMMemPoolsSet * s_GetCurPoolsSet(void)
static void s_DeallocMemory(void *ptr)
static const Uint1 kMMCntFreeGrades
static bool s_IsInFreeList(SMMPageHeader *page)
static void s_IncPoolIdx(Uint2 &idx)
static void s_SysFree(void *ptr, size_t size)
static const size_t kMMOSPageMask
static bool s_RemoveFromFreeList(SMMPageHeader *page, Uint2 size_idx)
static const Uint2 kMMCntBlocksInPool
static bool s_HadMemMgrInit
static void s_PrintBlocksState(CSrvPrintProxy &proxy, Int8 *start_blocks, Int8 *end_blocks)
static SMMPageHeader * s_AllocNewPage(Uint2 size_idx, SMMStat *)
static void * s_FillPool(SMMBlocksPool *pool, SMMStat *stat)
static void s_FreeListAddTail(SMMPageHeader *list_head, SMMPageHeader *page)
static void * s_FillFromFreePages(SMMBlocksPool *pool, Uint2 size_idx, SMMStat *stat)
static const Uint4 kMMPageDataSize
static void s_DoUnmap(void *ptr, size_t size)
static void s_FreeListAddHead(SMMPageHeader *list_head, SMMPageHeader *page)
static void * s_DoMmap(size_t size)
static Int8 s_TotalPageCount
#define __NC_MEMMAN_DEBUG
static Uint8 s_TotalSysMem
static Uint2 kMMCntForSize[kMMCntBlockSizes]
static const Uint2 kMMDrainBatchSize
static SMMPageHeader * s_GetPageByPtr(void *ptr)
static size_t s_CalcBigPageSize(size_t size)
static const int kMMFlushPeriod
static void s_LowLevelInit(void)
static void s_FlushPoolSet(SMMMemPoolsSet *pool_set)
static bool s_IsFreeListEmpty(SMMPageHeader *list_head)
static bool s_HadLowLevelInit
static void s_FreeListRemove(SMMPageHeader *page)
static void * s_AllocMemory(size_t size)
static const Uint4 kMMAllocPageSize
If for some reason kMMAllocPageSize is changed then kMMMaxBlockSize will change too and thus probably...
void ReleaseThreadMemMgr(SSrvThread *thr)
static void s_DrainPool(SMMBlocksPool *pool, void *ptr, SMMStat *stat)
void FinalizeMemoryMan(void)
static void s_PutToFreeList(SMMPageHeader *page, Uint2 size_idx, bool to_head)
static void * s_SysAlloc(size_t size)
static void * s_GetFromPool(SMMBlocksPool *pool, SMMStat *stat)
static void s_PrintSizeDiff(CSrvPrintProxy &proxy, Uint2 size_idx, Int8 was_blocks, Int8 is_blocks)
Uint8 s_UserBlAlloced[kMMCntBlockSizes]
static const Uint2 kMMOSPageSize
This is Linux standard on x86_64.
static void s_DeallocBigPage(SMMPageHeader *page, SMMStat *)
static SMMStateStat s_StartState
static Uint2 s_CalcSizeIndex(size_t size)
static SMMMemPoolsSet s_GlobalPoolsSet
static const Uint2 kMMMaxBlockSize
static void * s_FillFromPage(SMMBlocksPool *pool, Uint2 size_idx, SMMPageHeader *page)
#define __NC_MEMMAN_PERTHREAD_STAT_ARG(x)
static void s_ReleaseToFreePages(void **blocks, Uint2 cnt, Uint2 size_idx, SMMStat *)
size_t GetMemSize(void *ptr)
static void * s_AllocBigPage(size_t size, SMMStat *)
Uint8 s_UserBlFreed[kMMCntBlockSizes]
static SMMMemPoolsSet s_MainPoolsSet
static const Uint2 kMMBlockSizes[kMMCntBlockSizes]
Uint8 s_SysBlFreed[kMMCntBlockSizes]
static void * s_ReallocMemory(void *ptr, size_t size)
static void * s_SysAllocLongWay(size_t ptr, size_t size)
Uint8 s_SysBlAlloced[kMMCntBlockSizes]
static const Uint2 kMMCntBlockSizes
const struct ncbi::grid::netcache::search::fields::SIZE size
#define SRV_LOG(sev, msg)
Macro to be used for printing log messages.
std::enable_if< std::is_unsigned< T >::value, string >::type g_ToSizeStr(T size)
string g_ToSmartStr(T num)
T AtomicAdd(T volatile &var, T add_value)
T AtomicSub(T volatile &var, T sub_value)
void * blocks[kMMCntBlocksInPool]
SMMFreePageList lists[kMMCntFreeGrades]
SMMBlocksPool pools[kMMCntBlockSizes]
void PrintToLogs(CRequestContext *ctx, CSrvPrintProxy &proxy)
Uint8 m_SysBlAlloced[kMMCntBlockSizes]
void TransferEndState(SMMStat *src_stat)
CSrvStatTerm< Uint8 > m_TotalDataMem
CSrvStatTerm< Uint8 > m_TotalSysMem
void CopyEndState(SMMStat *src_stat)
Uint8 m_UserBlAlloced[kMMCntBlockSizes]
SMMStateStat m_StartState
void x_PrintUnstructured(CSrvPrintProxy &proxy)
void SaveEndStateStat(SMMStat *src_stat)
Uint8 m_UserBlFreed[kMMCntBlockSizes]
Uint8 m_SysBlFreed[kMMCntBlockSizes]
void PrintToSocket(CSrvPrintProxy &proxy)
void CopyStartState(SMMStat *src_stat)
void AddStats(SMMStat *src_stat)
void PrintState(CSrvSocketTask &task)
void InitStartState(void)
Int8 m_UserBlocks[kMMCntBlockSizes]
Int8 m_SysBlocks[kMMCntBlockSizes]
static DP_BlockInfo * blocks
Uint2 TSrvThreadNum
Type for thread number in TaskServer.
CRef< CTestThread > thr[k_NumThreadsMax]
SSrvThread * GetCurThread(void)
void InitCurThreadStorage(void)