소스 검색

gc: added dedicated pages for >1MB large blocks (reduces fragmentation) + GC_PRINT_ALLOCS_SIZES for sizes stats

Nicolas Cannasse 5 년 전
부모
커밋
a128cbb90c
2개의 변경된 파일36개의 추가작업 그리고 3개의 파일을 삭제
  1. 11 3
      src/allocator.c
  2. 25 0
      src/gc.c

+ 11 - 3
src/allocator.c

@@ -47,13 +47,15 @@ static inline unsigned int TRAILING_ZEROES( unsigned int x ) {
 #define GC_PARTITIONS	9
 #define GC_PART_BITS	4
 #define GC_FIXED_PARTS	5
-static const int GC_SBITS[GC_PARTITIONS] = {0,0,0,0,0,		3,6,14,22};
+#define GC_LARGE_PART	(GC_PARTITIONS-1)
+#define GC_LARGE_BLOCK	(1 << 20)
+static const int GC_SBITS[GC_PARTITIONS] = {0,0,0,0,0,		3,6,13,0};
 
 #ifdef HL_64
-static const int GC_SIZES[GC_PARTITIONS] = {8,16,24,32,40,	8,64,1<<14,1<<22};
+static const int GC_SIZES[GC_PARTITIONS] = {8,16,24,32,40,	8,64,1<<13,0};
 #	define GC_ALIGN_BITS		3
 #else
-static const int GC_SIZES[GC_PARTITIONS] = {4,8,12,16,20,	8,64,1<<14,1<<22};
+static const int GC_SIZES[GC_PARTITIONS] = {4,8,12,16,20,	8,64,1<<13,0};
 #	define GC_ALIGN_BITS		2
 #endif
 
@@ -280,6 +282,12 @@ alloc_var:
 static void *gc_allocator_alloc( int *size, int page_kind ) {
 	int sz = *size;
 	sz += (-sz) & (GC_ALIGN - 1);
+	if( sz >= GC_LARGE_BLOCK ) {
+		sz += (-sz) & (GC_PAGE_SIZE - 1);
+		*size = sz;
+		gc_pheader *ph = gc_allocator_new_page((GC_LARGE_PART << PAGE_KIND_BITS) | page_kind,sz,sz,page_kind,false);
+		return ph->base;
+	}
 	if( sz <= GC_SIZES[GC_FIXED_PARTS-1] && page_kind != MEM_KIND_FINALIZER ) {
 		int part = (sz >> GC_ALIGN_BITS) - 1;
 		*size = GC_SIZES[part];

+ 25 - 0
src/gc.c

@@ -470,6 +470,31 @@ void *hl_gc_alloc_gen( hl_type *t, int size, int flags ) {
 		allocated = size;
 		gc_stats.allocation_count++;
 		gc_stats.total_requested += size;
+#		ifdef GC_PRINT_ALLOCS_SIZES
+#		define MAX_WORDS 16
+		static int SIZE_CATEGORIES[MAX_WORDS] = {0};
+		static int LARGE_BLOCKS[33] = {0};
+		int wsize = (size + sizeof(void*) - 1) & ~(sizeof(void*)-1);
+		if( wsize < MAX_WORDS * sizeof(void*) )
+			SIZE_CATEGORIES[wsize/sizeof(void*)]++;
+		else {
+			int k = 0;
+			while( size > (1<<k) && k < 20 ) {
+				k++;
+			}
+			LARGE_BLOCKS[k]++;
+		}
+		if( (gc_stats.allocation_count & 0xFFFF) == 0 ) {
+			int i;
+			for(i=0;i<MAX_WORDS;i++)
+				if( SIZE_CATEGORIES[i] )
+					printf("%d=%.1f ",i*sizeof(void*),(SIZE_CATEGORIES[i] * 100.) / gc_stats.allocation_count);
+			for(i=0;i<33;i++)
+				if( LARGE_BLOCKS[i] )
+					printf("%d=%.2f ",1<<i,(LARGE_BLOCKS[i] * 100.) / gc_stats.allocation_count);
+			printf("%d\n",gc_stats.allocation_count);
+		}
+#		endif
 		ptr = gc_allocator_alloc(&allocated,flags & PAGE_KIND_MASK);
 		if( ptr == NULL ) {
 			if( allocated < 0 ) {