IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 19, 2004, 10:45:53 AM (22 years ago)
Author:
desonia
Message:

added recycling of small memory blocks as according to Lupton's suggestions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/sysUtils/psMemory.c

    r1233 r1240  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-07-15 23:52:34 $
     10 *  @version $Revision: 1.29 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-07-19 20:45:53 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    2828#define P_PS_MEMMAGIC (void *)0xdeadbeef // Magic number in psMemBlock header
    2929
     30#define P_PS_LARGE_BLOCK_SIZE 65536    // size where under, we try to recycle
     31
    3032static int checkMemBlock(const psMemBlock *m, const char* funcName);
    3133static psMemBlock *lastMemBlockAllocated = NULL;
     
    3335static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;
    3436
     37static pthread_mutex_t recycleMemBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
     38
     39static int recycleBins = 13;
     40static int recycleBinSize[14] = {8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,P_PS_LARGE_BLOCK_SIZE};
     41// N.B. recycleBinSize should be terminated by P_PS_LARGE_BLOCK_SIZE (simplifies search loops)
     42static psMemBlock* recycleMemBlockList[13] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
     43
     44#ifdef PS_MEM_DEBUG
     45static psMemBlock* deadBlockList;    // a place to put dead memBlocks in debug mode.
     46#endif
    3547/**
    3648 * Unique ID for allocated blocks
     
    4355static void *memExhaustedCallbackDefault(size_t size)
    4456{
    45     return NULL;
     57    void* ptr = NULL;
     58
     59    pthread_mutex_lock(&recycleMemBlockListMutex);
     60    int level=recycleBins-1;
     61    while (level >= 0 && ptr == NULL) {
     62        while (recycleMemBlockList[level] != NULL && ptr == NULL) {
     63            psMemBlock* old = recycleMemBlockList[level];
     64            recycleMemBlockList[level] = recycleMemBlockList[level]->nextBlock;
     65            free(old);
     66            ptr = malloc(size);
     67        }
     68        level--;
     69    }
     70    pthread_mutex_unlock(&recycleMemBlockListMutex);
     71
     72    return ptr;
    4673}
    4774
     
    243270void *p_psAlloc(size_t size, const char *file, int lineno)
    244271{
    245     psMemBlock *ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));
     272
     273    psMemBlock *ptr = NULL;
     274
     275    // memory is of the size I want to bother recycling?
     276    if (size < P_PS_LARGE_BLOCK_SIZE) {
     277        // find the bin we need.
     278        int level = 0;
     279        while (size > recycleBinSize[level]) {
     280            level++;
     281        }
     282        // Are we in one of the bins
     283        if (level<recycleBins) {
     284
     285            size = recycleBinSize[level];  // round-up size to next sized bin.
     286
     287            pthread_mutex_lock(&recycleMemBlockListMutex);
     288
     289            if (recycleMemBlockList[level] != NULL) {
     290                ptr = recycleMemBlockList[level];
     291                recycleMemBlockList[level] = ptr->nextBlock;
     292                if (recycleMemBlockList[level] != NULL) {
     293                    recycleMemBlockList[level]->previousBlock = NULL;
     294                }
     295                size = ptr->userMemorySize;
     296            }
     297
     298            pthread_mutex_unlock(&recycleMemBlockListMutex);
     299        }
     300    }
    246301
    247302    if (ptr == NULL) {
    248         ptr = memExhaustedCallback(size);
     303        ptr = malloc(sizeof(psMemBlock) + size + sizeof(void*));
     304
    249305        if (ptr == NULL) {
    250             psAbort(__func__, "Failed to allocate %u bytes at %s:%d",
    251                     size, file, lineno);
    252         }
     306            ptr = memExhaustedCallback(size);
     307            if (ptr == NULL) {
     308                psAbort(__func__, "Failed to allocate %u bytes at %s:%d",
     309                        size, file, lineno);
     310            }
     311        }
     312
     313        ptr->startblock = P_PS_MEMMAGIC;
     314        ptr->endblock = P_PS_MEMMAGIC;
     315        ptr->userMemorySize = size;
     316        pthread_mutex_init(&ptr->refCounterMutex, NULL);
    253317    }
    254318
     
    261325    ptr->freeFcn = NULL;
    262326    *(unsigned int*)&ptr->lineno = lineno;
    263     ptr->startblock = P_PS_MEMMAGIC;
    264     ptr->endblock = P_PS_MEMMAGIC;
    265     ptr->userMemorySize = size;
    266327    *(void**)((int8_t*)(ptr+1)+size) = P_PS_MEMMAGIC;
    267328    ptr->previousBlock = NULL;
    268329
    269     pthread_mutex_init(&ptr->refCounterMutex, NULL);
    270330    ptr->refCounter = 1;                // one user so far
    271331
     
    475535        }
    476536
    477         #ifdef PS_MEM_DEBUG
    478         // for debug mode, we should keep the memBlock around and mark as not referenced.
    479         ptr->refCounter = 0;
    480         (void)p_psRealloc(vptr,0,file,lineno);
    481         #else
    482 
    483537        pthread_mutex_lock(&memBlockListMutex);
    484538
     
    496550        pthread_mutex_unlock(&memBlockListMutex);
    497551
     552
     553        // do we need to recycle?
     554        if (ptr->userMemorySize < P_PS_LARGE_BLOCK_SIZE) {
     555
     556            int level = 1;
     557            while (ptr->userMemorySize >= recycleBinSize[level]) {
     558                level++;
     559            }
     560            level--;
     561
     562            ptr->refCounter = 0;
     563            ptr->previousBlock = NULL;
     564
     565            pthread_mutex_lock(&recycleMemBlockListMutex);
     566            ptr->nextBlock = recycleMemBlockList[level];
     567            if (recycleMemBlockList[level] != NULL) {
     568                recycleMemBlockList[level]->previousBlock = ptr;
     569            }
     570            recycleMemBlockList[level] = ptr;
     571            pthread_mutex_unlock(&recycleMemBlockListMutex);
     572
     573        } else {
     574            // memory is larger than I want to recycle.
     575            #ifdef PS_MEM_DEBUG
     576            (void)p_psRealloc(vptr,0,file,lineno);
     577            ptr->previousBlock = NULL;
     578            ptr->nextBlock = deadBlockList;
     579            if (deadBlockList != NULL) {
     580                deadBlockList->previous = ptr;
     581            }
     582            deadBlockList = ptr;
     583            #else
     584
     585            pthread_mutex_destroy(&ptr->refCounterMutex);
     586            free(ptr);
     587            #endif
     588
     589        }
     590
     591
    498592        pthread_mutex_destroy(&ptr->refCounterMutex);
    499593
    500         free(ptr);
    501         #endif
    502594
    503595        vptr = NULL;    // since we freed it, make sure we return NULL.
Note: See TracChangeset for help on using the changeset viewer.