Commit e905bad9816b19fa0004a54d2cda7ba840ca6b93
1 parent
0c2907f9
optimize allocation for GNU systems. That is allocate only blocks of a size malloc handles.
Showing
1 changed file
with
43 additions
and
96 deletions
| @@ -623,65 +623,13 @@ deleteElement(struct memSegment ** tree, struct memSegment * element) | @@ -623,65 +623,13 @@ deleteElement(struct memSegment ** tree, struct memSegment * element) | ||
| 623 | return del_node; | 623 | return del_node; |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | - | ||
| 627 | -//static | ||
| 628 | -//void | ||
| 629 | -//traverse(struct memSegment * tree, void (*cb)(struct memSegment *, int)) | ||
| 630 | -//{ | ||
| 631 | -// struct memSegment * previous = tree; | ||
| 632 | -// struct memSegment * node = tree; | ||
| 633 | -// int depth = 1; | ||
| 634 | -// | ||
| 635 | -// /* | ||
| 636 | -// * I think this has something like O(n+log(n)) on a ballanced | ||
| 637 | -// * tree because I have to traverse back the rightmost leaf to | ||
| 638 | -// * the root to get a break condition. | ||
| 639 | -// */ | ||
| 640 | -// while (node) { | ||
| 641 | -// /* | ||
| 642 | -// * If we come from the right so nothing and go to our | ||
| 643 | -// * next parent. | ||
| 644 | -// */ | ||
| 645 | -// if (previous == node->right) { | ||
| 646 | -// previous = node; | ||
| 647 | -// node = node->parent; | ||
| 648 | -// depth--; | ||
| 649 | -// continue; | ||
| 650 | -// } | ||
| 651 | -// | ||
| 652 | -// if ((NULL == node->left || previous == node->left)) { | ||
| 653 | -// /* | ||
| 654 | -// * If there are no more elements to the left or we | ||
| 655 | -// * came from the left, process data. | ||
| 656 | -// */ | ||
| 657 | -// cb(node, depth); | ||
| 658 | -// previous = node; | ||
| 659 | -// | ||
| 660 | -// if (NULL != node->right) { | ||
| 661 | -// node = node->right; | ||
| 662 | -// depth++; | ||
| 663 | -// } else { | ||
| 664 | -// node = node->parent; | ||
| 665 | -// depth--; | ||
| 666 | -// } | ||
| 667 | -// } else { | ||
| 668 | -// /* | ||
| 669 | -// * if there are more elements to the left go there. | ||
| 670 | -// */ | ||
| 671 | -// previous = node; | ||
| 672 | -// node = node->left; | ||
| 673 | -// depth++; | ||
| 674 | -// } | ||
| 675 | -// } | ||
| 676 | -//} | ||
| 677 | - | ||
| 678 | static | 626 | static |
| 679 | void | 627 | void |
| 680 | post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) | 628 | post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) |
| 681 | { | 629 | { |
| 682 | struct memSegment * previous = tree; | 630 | struct memSegment * previous = tree; |
| 683 | struct memSegment * node = tree; | 631 | struct memSegment * node = tree; |
| 684 | - int depth = 1; | 632 | + int depth = 1; |
| 685 | 633 | ||
| 686 | /* | 634 | /* |
| 687 | * I think this has something like O(n+log(n)) on a ballanced | 635 | * I think this has something like O(n+log(n)) on a ballanced |
| @@ -732,42 +680,6 @@ post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) | @@ -732,42 +680,6 @@ post(struct memSegment * tree, void (*cb)(struct memSegment *, int)) | ||
| 732 | } | 680 | } |
| 733 | } | 681 | } |
| 734 | 682 | ||
| 735 | -//void | ||
| 736 | -//printElement(struct memSegment * node, int depth) | ||
| 737 | -//{ | ||
| 738 | -// int i; | ||
| 739 | -// | ||
| 740 | -// printf("%s %010zu:%p(%02d)", | ||
| 741 | -// (node->color==rbRed)?"R":"B", | ||
| 742 | -// node->size, | ||
| 743 | -// node->ptr, | ||
| 744 | -// depth); | ||
| 745 | -// for (i=0; i<depth; i++) printf("-"); | ||
| 746 | -// puts(""); | ||
| 747 | -// | ||
| 748 | -// node = node->next; | ||
| 749 | -// while (NULL != node) { | ||
| 750 | -// printf(" %s %010zu:%p(%02d)", | ||
| 751 | -// (node->color==rbRed)?"R":"B", | ||
| 752 | -// node->size, | ||
| 753 | -// node->ptr, | ||
| 754 | -// depth); | ||
| 755 | -// for (i=0; i<depth; i++) printf("-"); | ||
| 756 | -// puts(""); | ||
| 757 | -// node = node->next; | ||
| 758 | -// } | ||
| 759 | -//} | ||
| 760 | - | ||
| 761 | -//void | ||
| 762 | -//cleanup(struct memSegment * node, int depth) | ||
| 763 | -//{ | ||
| 764 | -// while (NULL != node) { | ||
| 765 | -// struct memSegment * next = node->next; | ||
| 766 | -// free(node); | ||
| 767 | -// node = next; | ||
| 768 | -// } | ||
| 769 | -//} | ||
| 770 | - | ||
| 771 | static | 683 | static |
| 772 | struct memSegment * segments = NULL; | 684 | struct memSegment * segments = NULL; |
| 773 | 685 | ||
| @@ -793,20 +705,55 @@ TR_reference(void * mem) | @@ -793,20 +705,55 @@ TR_reference(void * mem) | ||
| 793 | } | 705 | } |
| 794 | 706 | ||
| 795 | /* | 707 | /* |
| 796 | - * This will always allocate a multiple of PAGESIZE | 708 | + * This tries to reflect the memory management behaviour of the |
| 709 | + * GNU version of malloc. For other versions this might need | ||
| 710 | + * to be changed to be optimal. | ||
| 711 | + * | ||
| 712 | + * However, GNU malloc keeps separate pools for each power of | ||
| 713 | + * 2 memory size up to page size. So one page consists all of | ||
| 714 | + * memory blocks of the same sizei (a power of 2). | ||
| 715 | + * | ||
| 716 | + * Also as far as I understand the smallest allocatable block is | ||
| 717 | + * 8 bytes. At least the adresses are alwayse a multiple of 8. | ||
| 718 | + * | ||
| 719 | + * So lets say page size is 4096. There is nothing allocated | ||
| 720 | + * right now. We allocate a block of 8 bytes. This will request | ||
| 721 | + * a memory page from the OS. Then define it as a page containing | ||
| 722 | + * 8 byte blocks and return the address of the first one of these. | ||
| 723 | + * Any subsequent call to malloc for 8 bytes will return one of the | ||
| 724 | + * blocks within this page as long as there are some left. | ||
| 725 | + * | ||
| 726 | + * So what we do here is up to page size round the request size up | ||
| 727 | + * to the next power of 2 >= 8. | ||
| 728 | + * Sizes greater then pagesize will be round up to the next | ||
| 729 | + * multiple of pagesize. As far as I understand these are not | ||
| 730 | + * pooled anyway. | ||
| 731 | + * | ||
| 732 | + * For now this assumes we are on a little endian machine. | ||
| 797 | */ | 733 | */ |
| 798 | void * | 734 | void * |
| 799 | TR_malloc(size_t size) | 735 | TR_malloc(size_t size) |
| 800 | { | 736 | { |
| 801 | - struct memSegment * seg = NULL; | ||
| 802 | - //long psize = sysconf(_SC_PAGESIZE); | ||
| 803 | - long psize = 64; | 737 | + struct memSegment * seg = NULL; |
| 738 | + long psize = sysconf(_SC_PAGESIZE); | ||
| 739 | + size_t check; | ||
| 804 | 740 | ||
| 805 | size += sizeof(struct memSegment); | 741 | size += sizeof(struct memSegment); |
| 806 | 742 | ||
| 807 | - /* allocate only blocks of a multiple of pagesize, similar to cbuf */ | ||
| 808 | - size = (0>=size)?1:(0!=size%psize)?(size/psize)+1:size/psize; | ||
| 809 | - size *= psize; | 743 | + if (size > psize) { |
| 744 | + if (0 != (size % psize)) { | ||
| 745 | + // size if not a multiple of pagesize so bring it to one. | ||
| 746 | + size = ((size / psize) + 1) * psize; | ||
| 747 | + } | ||
| 748 | + } else { | ||
| 749 | + check = size >> 1; | ||
| 750 | + check = (size | check) - check; | ||
| 751 | + | ||
| 752 | + if (check != size) { | ||
| 753 | + // size is not a power of 2 so bring it to one. | ||
| 754 | + size = ((size << 1) | size) - size; | ||
| 755 | + } | ||
| 756 | + } | ||
| 810 | 757 | ||
| 811 | #ifdef MEM_OPT | 758 | #ifdef MEM_OPT |
| 812 | seg = findElement(segments, size); | 759 | seg = findElement(segments, size); |
Please
register
or
login
to post a comment