VirtualBox

Ignore:
Timestamp:
Feb 11, 2010 6:41:06 PM (15 years ago)
Author:
vboxsync
Message:

iprt/memcache.h: Some more optimizations and more benchmarks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/alloc/memcache.cpp

    r26428 r26452  
    5353/** Pointer to a cache page. */
    5454typedef struct RTMEMCACHEPAGE *PRTMEMCACHEPAGE;
     55
     56
     57
     58/**
     59 * A free object.
     60 *
     61 * @remarks This only works if the objects don't have a constructor or
     62 *          destructor and are big enough.
     63 */
     64typedef struct RTMEMCACHEFREEOBJ
     65{
     66    /** Pointer to the next free object  */
     67    struct RTMEMCACHEFREEOBJ * volatile pNext;
     68} RTMEMCACHEFREEOBJ;
     69/** Pointer to a free object. */
     70typedef RTMEMCACHEFREEOBJ *PRTMEMCACHEFREEOBJ;
    5571
    5672
     
    107123    /** The maximum number of objects. */
    108124    uint32_t                    cMax;
     125    /** Whether to the use the free list or not. */
     126    bool                        fUseFreeList;
    109127    /** Head of the page list. */
    110128    PRTMEMCACHEPAGE             pPageHead;
     
    124142    /** This may point to a page with free entries. */
    125143    PRTMEMCACHEPAGE volatile    pPageHint;
     144    /** Stack of free items.
     145     * These are marked as used in the allocation bitmaps.
     146     *
     147     * @todo This doesn't scale well when several threads are beating on the
     148     *       cache.  Also, it totally doesn't work when we've got a
     149     *       constructor/destructor around or the objects are too small. */
     150    PRTMEMCACHEFREEOBJ volatile pFreeTop;
    126151} RTMEMCACHEINT;
    127152
     
    129154
    130155RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects,
    131                              PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser)
     156                             PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags)
     157
    132158{
    133159    AssertPtr(phMemCache);
    134160    AssertPtrNull(pfnCtor);
    135161    AssertPtrNull(pfnDtor);
     162    AssertReturn(!pfnDtor || pfnCtor, VERR_INVALID_PARAMETER);
    136163    AssertReturn(cbObject > 0, VERR_INVALID_PARAMETER);
    137164    AssertReturn(cbObject <= PAGE_SIZE / 8, VERR_INVALID_PARAMETER);
     165    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
    138166
    139167    if (cbAlignment == 0)
     
    173201    pThis->cBits            = RT_ALIGN(pThis->cPerPage, 64);
    174202    pThis->cMax             = cMaxObjects;
    175     pThis->cTotal           = 0;
    176     pThis->cFree            = 0;
     203    pThis->fUseFreeList     = cbObject >= sizeof(RTMEMCACHEFREEOBJ)
     204                           && !pfnCtor
     205                           && !pfnDtor;
    177206    pThis->pPageHead        = NULL;
    178     pThis->pPageHint        = NULL;
    179207    pThis->pfnCtor          = pfnCtor;
    180208    pThis->pfnDtor          = pfnDtor;
    181209    pThis->pvUser           = pvUser;
     210    pThis->cTotal           = 0;
     211    pThis->cFree            = 0;
     212    pThis->pPageHint        = NULL;
     213    pThis->pFreeTop         = NULL;
    182214
    183215    *phMemCache = pThis;
     
    193225    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    194226    AssertReturn(pThis->u32Magic == RTMEMCACHE_MAGIC, VERR_INVALID_HANDLE);
    195     AssertMsg((uint32_t)pThis->cFree == pThis->cTotal, ("cFree=%u cTotal=%u\n", pThis->cFree, pThis->cTotal));
     227#ifdef RT_STRICT
     228    uint32_t cFree = pThis->cFree;
     229    for (PRTMEMCACHEFREEOBJ pFree = pThis->pFreeTop; pFree; pFree = pFree->pNext)
     230        cFree++;
     231    AssertMsg(cFree == pThis->cTotal, ("cFree=%u cTotal=%u\n", cFree, pThis->cTotal));
     232#endif
    196233
    197234    /*
     
    268305            pb = (uint8_t *)((uintptr_t)pb & ~(uintptr_t)7);
    269306            pPage->pbmAlloc     = pb;
    270             Assert((uintptr_t)pPage->pbmCtor + pThis->cBits / 8 < (uintptr_t)pPage->pbmCtor);
     307            Assert((uintptr_t)pPage->pbmCtor + pThis->cBits / 8 <= (uintptr_t)pPage->pbmAlloc);
    271308
    272309            /* Mark the bitmap padding and any unused objects as allocated. */
     
    322359    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
    323360    AssertReturn(pThis->u32Magic == RTMEMCACHE_MAGIC, VERR_INVALID_PARAMETER);
     361
     362    /*
     363     * Try grab a free object from the stack.
     364     */
     365    PRTMEMCACHEFREEOBJ pObj = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop);
     366    if (pObj)
     367    {
     368        PRTMEMCACHEFREEOBJ pNext;
     369        do
     370        {
     371            pNext = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pObj->pNext);
     372            if (ASMAtomicCmpXchgPtr((void * volatile *)&pThis->pFreeTop, pNext, pObj))
     373            {
     374                *ppvObj = pObj;
     375                return VINF_SUCCESS;
     376            }
     377            pObj = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop);
     378        } while (pObj);
     379    }
    324380
    325381    /*
     
    438494    Assert(RT_ALIGN_P(pvObj, pThis->cbAlignment) == pvObj);
    439495
    440     /* Note: Do *NOT* attempt to poison the object if we have a constructor
    441              or/and destructor! */
    442 
    443     /*
    444      * Find the cache page.  The page structure is at the start of the page.
    445      */
    446     PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK);
    447     Assert(pPage->pCache == pThis);
    448     Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage);
    449 
    450     /*
    451      * Clear the bitmap bit and update the two object counter. Order matters!
    452      */
    453     uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects;
    454     uintptr_t iObj   = offObj / pThis->cbObject;
    455     Assert(iObj * pThis->cbObject == offObj);
    456     Assert(iObj < pThis->cPerPage);
    457     AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj));
    458 
    459     ASMAtomicIncS32(&pPage->cFree);
    460     ASMAtomicIncS32(&pThis->cFree);
    461 }
    462 
     496    if (pThis->fUseFreeList)
     497    {
     498# ifdef RT_STRICT
     499        /* This is the same as the other branch, except it's not actually freed. */
     500        PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK);
     501        Assert(pPage->pCache == pThis);
     502        Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage);
     503        uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects;
     504        uintptr_t iObj   = offObj / pThis->cbObject;
     505        Assert(iObj * pThis->cbObject == offObj);
     506        Assert(iObj < pThis->cPerPage);
     507        AssertReturnVoid(ASMBitTest(pPage->pbmAlloc, iObj));
     508# endif
     509
     510        /*
     511         * Push it onto the free stack.
     512         */
     513        PRTMEMCACHEFREEOBJ pObj = (PRTMEMCACHEFREEOBJ)pvObj;
     514        PRTMEMCACHEFREEOBJ pNext;
     515        do
     516        {
     517            pNext = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop);
     518            pObj->pNext = pNext;
     519        } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pThis->pFreeTop, pObj, pNext));
     520    }
     521    else
     522    {
     523        /* Note: Do *NOT* attempt to poison the object if we have a constructor
     524                 or/and destructor! */
     525
     526        /*
     527         * Find the cache page.  The page structure is at the start of the page.
     528         */
     529        PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK);
     530        Assert(pPage->pCache == pThis);
     531        Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage);
     532
     533        /*
     534         * Clear the bitmap bit and update the two object counter. Order matters!
     535         */
     536        uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects;
     537        uintptr_t iObj   = offObj / pThis->cbObject;
     538        Assert(iObj * pThis->cbObject == offObj);
     539        Assert(iObj < pThis->cPerPage);
     540        AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj));
     541
     542        ASMAtomicIncS32(&pPage->cFree);
     543        ASMAtomicIncS32(&pThis->cFree);
     544    }
     545}
     546
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette