Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | New function TclAllocMaximize(). Let tclListObj.c find out the real allocated size, thus reducing the number of reallocs. It's good to avoid the interplay between List and Alloc both doubling just-in-case. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | mig-alloc-reform |
Files: | files | file ages | folders |
SHA1: |
b8f22672b20ef57964ed0cf47ce82ad3 |
User & Date: | mig 2011-03-18 16:16:09 |
Context
2011-03-18
| ||
18:06 | remove unused mutex check-in: a3f0c08c7f user: mig tags: mig-alloc-reform | |
16:16 | New function TclAllocMaximize(). Let tclListObj.c find out the real allocated size, thus reducing th... check-in: b8f22672b2 user: mig tags: mig-alloc-reform | |
13:32 | README addition check-in: 3e9d5dacd9 user: mig tags: mig-alloc-reform | |
Changes
Changes to generic/tclAlloc.c.
︙ | ︙ | |||
193 194 195 196 197 198 199 | #define OFFSET ALIGN(sizeof(Block)) #define nextBlock u.next #define sourceBucket u.s.bucket #define magicNum1 u.s.magic1 #define magicNum2 u.s.magic2 #define MAGIC 0xEF | < | 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | #define OFFSET ALIGN(sizeof(Block)) #define nextBlock u.next #define sourceBucket u.s.bucket #define magicNum1 u.s.magic1 #define magicNum2 u.s.magic2 #define MAGIC 0xEF /* * The following defines the minimum and maximum block sizes and the number * of buckets in the bucket cache. * 32b 64b Apple-32b * TCL_ALLOCALIGN 8 16 16 * sizeof(Block) 8 16 16 |
︙ | ︙ | |||
381 382 383 384 385 386 387 | int bucket, unsigned int reqSize) { register void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; | | | | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 | int bucket, unsigned int reqSize) { register void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; blockPtr->reqSize = reqSize; ptr = (void *) (((char *)blockPtr) + OFFSET); #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; #endif return (char *) ptr; } static inline Block * Ptr2Block( char *ptr) { register Block *blockPtr; blockPtr = (Block *) (((char *) ptr) - OFFSET); if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2); } #if RCHECK if (((unsigned char *) ptr)[blockPtr->reqSize] != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2, ((unsigned char *) ptr)[blockPtr->reqSize]); } #endif return blockPtr; } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
703 704 705 706 707 708 709 | * blocks to the shared cache if there are now too many free. */ blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == nBuckets) { #ifdef ZIPPY_STATS | | | | 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | * blocks to the shared cache if there are now too many free. */ blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == nBuckets) { #ifdef ZIPPY_STATS cachePtr->totalAssigned -= blockPtr->reqSize; #endif free(blockPtr); return; } #ifdef ZIPPY_STATS cachePtr->buckets[bucket].totalAssigned -= blockPtr->reqSize; #endif blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; cachePtr->buckets[bucket].numFree++; #ifdef ZIPPY_STATS cachePtr->buckets[bucket].numInserts++; #endif |
︙ | ︙ | |||
796 797 798 799 800 801 802 | if (bucket > 0) { min = bucketInfo[bucket-1].blockSize; } else { min = 0; } if (size > min && size <= bucketInfo[bucket].blockSize) { #ifdef ZIPPY_STATS | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 | if (bucket > 0) { min = bucketInfo[bucket-1].blockSize; } else { min = 0; } if (size > min && size <= bucketInfo[bucket].blockSize) { #ifdef ZIPPY_STATS cachePtr->buckets[bucket].totalAssigned -= blockPtr->reqSize; cachePtr->buckets[bucket].totalAssigned += reqSize; #endif return Block2Ptr(blockPtr, bucket, reqSize); } } else if (size > MAXALLOC) { #ifdef ZIPPY_STATS cachePtr->totalAssigned -= blockPtr->reqSize; cachePtr->totalAssigned += reqSize; #endif blockPtr = realloc(blockPtr, size); if (blockPtr == NULL) { return NULL; } return Block2Ptr(blockPtr, nBuckets, reqSize); } /* * Finally, perform an expensive malloc/copy/free. */ newPtr = TclpAlloc(reqSize); if (newPtr != NULL) { if (reqSize > blockPtr->reqSize) { reqSize = blockPtr->reqSize; } memcpy(newPtr, ptr, reqSize); TclpFree(ptr); } return newPtr; } /* *---------------------------------------------------------------------- * * TclAllocMaximize -- * * Given a TclpAlloc'ed pointer, it returns the maximal size that can be used * by the allocated memory. This is almost always larger than the requested * size, as it corresponds to the bucket's size. * * Results: * New size. * *---------------------------------------------------------------------- */ unsigned int TclAllocMaximize( void *ptr) { Block *blockPtr; int bucket; size_t oldSize, newSize; if (allocator < aNONE) { /* * No info, return UINT_MAX as a signal. */ return UINT_MAX; } blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == nBuckets) { /* * System malloc'ed: no info */ return UINT_MAX; } oldSize = blockPtr->reqSize; newSize = bucketInfo[bucket].blockSize - OFFSET - RCHECK; blockPtr->reqSize = newSize; #if RCHECK ((unsigned char *)(ptr))[newSize] = MAGIC; #endif return newSize; } #ifdef ZIPPY_STATS /* *---------------------------------------------------------------------- * * Tcl_GetMemoryInfo -- * |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 | # endif #endif #if TCL_ALLOCATOR < aNONE /* native or purify */ # define TclpAlloc(size) ckalloc(size) # define TclpRealloc(ptr, size) ckrealloc((ptr),(size)) # define TclpFree(size) ckfree(size) #else MODULE_SCOPE char * TclpAlloc(unsigned int size); MODULE_SCOPE char * TclpRealloc(char * ptr, unsigned int size); MODULE_SCOPE void TclpFree(char * ptr); #endif #if TCL_ALLOCATOR == aPURIFY # define TclSmallAlloc() ckalloc(sizeof(Tcl_Obj)) # define TclSmallFree(ptr) ckfree(ptr) # define TclInitAlloc() # define TclFinalizeAlloc() | > > | 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 | # endif #endif #if TCL_ALLOCATOR < aNONE /* native or purify */ # define TclpAlloc(size) ckalloc(size) # define TclpRealloc(ptr, size) ckrealloc((ptr),(size)) # define TclpFree(size) ckfree(size) # define TclAllocMaximize(ptr) UINT_MAX #else MODULE_SCOPE char * TclpAlloc(unsigned int size); MODULE_SCOPE char * TclpRealloc(char * ptr, unsigned int size); MODULE_SCOPE void TclpFree(char * ptr); MODULE_SCOPE unsigned int TclAllocMaximize(void *ptr); #endif #if TCL_ALLOCATOR == aPURIFY # define TclSmallAlloc() ckalloc(sizeof(Tcl_Obj)) # define TclSmallFree(ptr) ckfree(ptr) # define TclInitAlloc() # define TclFinalizeAlloc() |
︙ | ︙ |
Changes to generic/tclListObj.c.
︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ static List * NewListIntRep( int objc, Tcl_Obj *const objv[]) { List *listRepPtr; | > > > > > > > > > > | | > | | > > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | * * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ #define Elems2Size(n) \ ((n > 1) \ ? (sizeof(List) + (n-1)*sizeof(Tcl_Obj *)) \ : (sizeof(List))) #define Size2Elems(s) \ ((s > sizeof(List) + sizeof(Tcl_Obj *) -1) \ ? (s - sizeof(List) + sizeof(Tcl_Obj *))/sizeof(Tcl_Obj *) \ : 1) static List * NewListIntRep( int objc, Tcl_Obj *const objv[]) { List *listRepPtr; unsigned int allocSize; if (objc <= 0) { return NULL; } /* * First check to see if we'd overflow and try to allocate an object * larger than our memory allocator allows. Note that this is actually a * fairly small value when you're on a serious 64-bit machine, but that * requires API changes to fix. See [Bug 219196] for a discussion. */ if ((size_t)objc > INT_MAX/sizeof(Tcl_Obj *)) { return NULL; } listRepPtr = attemptckalloc(Elems2Size(objc)); if (listRepPtr == NULL) { return NULL; } allocSize = TclAllocMaximize(listRepPtr); listRepPtr->canonicalFlag = 0; listRepPtr->refCount = 0; listRepPtr->maxElemCount = (allocSize == UINT_MAX) ? objc : Size2Elems(allocSize); if (objv) { Tcl_Obj **elemPtrs; int i; listRepPtr->elemCount = objc; elemPtrs = &listRepPtr->elements; |
︙ | ︙ | |||
572 573 574 575 576 577 578 | * If there is no room in the current array of element pointers, allocate * a new, larger array and copy the pointers to it. If the List struct is * shared, allocate a new one. */ if (numRequired > listRepPtr->maxElemCount){ newMax = 2 * numRequired; | | | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | * If there is no room in the current array of element pointers, allocate * a new, larger array and copy the pointers to it. If the List struct is * shared, allocate a new one. */ if (numRequired > listRepPtr->maxElemCount){ newMax = 2 * numRequired; newSize = Elems2Size(newMax); } else { newMax = listRepPtr->maxElemCount; newSize = 0; } if (listRepPtr->refCount > 1) { List *oldListRepPtr = listRepPtr; |
︙ | ︙ | |||
597 598 599 600 601 602 603 | Tcl_IncrRefCount(elemPtrs[i]); } listRepPtr->elemCount = numElems; listRepPtr->refCount++; oldListRepPtr->refCount--; } else if (newSize) { listRepPtr = ckrealloc(listRepPtr, newSize); | > | > > | 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 | Tcl_IncrRefCount(elemPtrs[i]); } listRepPtr->elemCount = numElems; listRepPtr->refCount++; oldListRepPtr->refCount--; } else if (newSize) { listRepPtr = ckrealloc(listRepPtr, newSize); newSize = TclAllocMaximize(listRepPtr); listRepPtr->maxElemCount = (newSize == UINT_MAX) ? newMax : Size2Elems(newSize); } listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; /* * Add objPtr to the end of listPtr's array of element pointers. Increment * the ref count for the (now shared) objPtr. */ |
︙ | ︙ |