浏览代码

use lookup map for faster compact()

Nicolas Cannasse 2 年之前
父节点
当前提交
f1afbbde42
共有 3 个文件被更改,包括 59 次插入50 次删除
  1. 28 0
      src/std/maps.c
  2. 17 5
      src/std/maps.h
  3. 14 45
      src/std/types.c

+ 28 - 0
src/std/maps.c

@@ -137,6 +137,8 @@ static int hl_freelist_get( hl_free_list *f ) {
 	return p;
 }
 
+#define _MVAL_TYPE vdynamic*
+
 // ----- INT MAP ---------------------------------
 
 typedef struct {
@@ -246,6 +248,32 @@ static vdynamic *hl_hofilter( vdynamic *key ) {
 
 #include "maps.h"
 
+// ----- LOOKUP MAP ---------------------------------
+
+#undef _MVAL_TYPE
+#define _MVAL_TYPE int
+
+typedef struct {
+	void *key;
+} hl_mlookup__entry;
+
+typedef struct {
+	int value;
+} hl_mlookup__value;
+
+#define hl_mlookup_hash(h) ((unsigned int)(int_val)(h))
+#define _MKEY_TYPE	void*
+#define _MNAME(n)	hl_mlookup_##n
+#define _MMATCH(c)	m->entries[c].key == key
+#define _MKEY(m,c)	m->entries[c].key
+#define	_MSET(c)	m->entries[c].key = key
+#define _MERASE(c)
+#define _MNO_EXPORTS
+
+#include "maps.h"
+
+/// ----------------------------------------------
+
 #define _IMAP _ABSTRACT(hl_int_map)
 DEFINE_PRIM( _IMAP, hialloc, _NO_ARG );
 DEFINE_PRIM( _VOID, hiset, _IMAP _I32 _DYN );

+ 17 - 5
src/std/maps.h

@@ -10,6 +10,11 @@
 #define _MLIMIT 128
 #define _MINDEX(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((signed char*)(m)->cells)[ckey] : ((int*)(m)->cells)[ckey])
 #define _MNEXT(m,ckey) ((m)->maxentries < _MLIMIT ? (int)((signed char*)(m)->nexts)[ckey] : ((int*)(m)->nexts)[ckey])
+#ifdef _MNO_EXPORTS
+#define _MSTATIC
+#else
+#define _MSTATIC static
+#endif
 
 typedef struct {
 	void *cells;
@@ -22,13 +27,16 @@ typedef struct {
 	int maxentries;
 } t_map;
 
-HL_PRIM t_map *_MNAME(alloc)() {
+#ifndef _MNO_EXPORTS
+HL_PRIM 
+#endif
+t_map *_MNAME(alloc)() {
 	t_map *m = (t_map*)hl_gc_alloc_raw(sizeof(t_map));
 	memset(m,0,sizeof(t_map));
 	return m;
 }
 
-static vdynamic **_MNAME(find)( t_map *m, t_key key ) {
+_MSTATIC _MVAL_TYPE *_MNAME(find)( t_map *m, t_key key ) {
 	int c, ckey;
 	unsigned int hash;
 
@@ -46,7 +54,7 @@ static vdynamic **_MNAME(find)( t_map *m, t_key key ) {
 
 static void _MNAME(resize)( t_map *m );
 
-static void _MNAME(set_impl)( t_map *m, t_key key, vdynamic *value ) {
+_MSTATIC void _MNAME(set_impl)( t_map *m, t_key key, _MVAL_TYPE value ) {
 	int c, ckey = 0;
 	unsigned int hash = _MNAME(hash)(key);
 	if( m->values ) {
@@ -125,7 +133,9 @@ static void _MNAME(resize)( t_map *m ) {
 	}
 }
 
-HL_PRIM void _MNAME(set)( t_map *m, t_key key, vdynamic *value ) {
+#ifndef _MNO_EXPORTS
+
+HL_PRIM void _MNAME(set)( t_map *m, t_key key, _MVAL_TYPE value ) {
 	_MNAME(set_impl)(m,_MNAME(filter)(key),value);
 }
 
@@ -211,8 +221,9 @@ HL_PRIM int _MNAME(size)( t_map *m ) {
 }
 
 
+#endif
+
 #undef hlt_key
-#undef hl_hbhash
 #undef _MKEY_TYPE
 #undef _MNAME
 #undef _MMATCH
@@ -222,3 +233,4 @@ HL_PRIM int _MNAME(size)( t_map *m ) {
 #undef _MOLD_KEY
 #undef _MINDEX
 #undef _MNEXT
+#undef _MSTATIC

+ 14 - 45
src/std/types.c

@@ -587,6 +587,10 @@ DEFINE_PRIM(_DYN, alloc_enum_dyn, _TYPE _I32 _ARR _I32);
 DEFINE_PRIM(_ARR, enum_parameters, _DYN);
 DEFINE_PRIM(_BOOL, type_set_global, _TYPE _DYN);
 
+typedef void hl_mlookup_map;
+extern hl_mlookup_map *hl_mlookup_alloc();
+extern int *hl_mlookup_find( hl_mlookup_map *m, void *key );
+extern void hl_mlookup_set_impl( hl_mlookup_map *m, void *key, int value );
 
 typedef struct {
 	char *buf;
@@ -595,10 +599,7 @@ typedef struct {
 	int *offsets;
 	int offsets_pos;
 	int offsets_size;
-	void **lookup;
-	int *lookup_index;
-	int lookup_pos;
-	int lookup_size;
+	hl_mlookup_map *lookup;
 	int *remap_target;
 	int remap_pos;
 	int remap_size;
@@ -641,50 +642,20 @@ static void compact_write_offset( mem_context *ctx, int position ) {
 	compact_write_ptr(ctx,(void*)(int_val)position);
 }
 
-static int compact_lookup_index( mem_context *ctx, void *addr ) {
-	int min = 0;
-	int max = ctx->lookup_pos;
-	while( min < max ) {
-		int mid = (min + max) >> 1;
-		void *a = ctx->lookup[mid];
-		if( a < addr ) min = mid + 1; else if( a > addr ) max = mid; else return mid;
-	}
-	return -1;
-}
-
 #define BYTE_MARK 0x40000000
 
 static int compact_lookup_ref( mem_context *ctx, void *addr, bool is_bytes ) {
-	int min = 0;
-	int max = ctx->lookup_pos;
-	while( min < max ) {
-		int mid = (min + max) >> 1;
-		void *a = ctx->lookup[mid];
-		if( a < addr ) min = mid + 1; else if( a > addr ) max = mid; else return ctx->remap_target[ctx->lookup_index[mid]&~BYTE_MARK];
-	}
-	if( ctx->lookup_pos == ctx->lookup_size ) {
-		int nsize = ctx->lookup_size == 0 ? 128 : (ctx->lookup_size * 3) / 2;
-		void **nlookup = (void**)malloc(nsize * sizeof(void*));
-		int *nindex = (int*)malloc(nsize * sizeof(int));
-		memcpy(nlookup,ctx->lookup,ctx->lookup_pos * sizeof(void*));
-		memcpy(nindex,ctx->lookup_index,ctx->lookup_pos * sizeof(int));
-		free(ctx->lookup);
-		free(ctx->lookup_index);
-		ctx->lookup = nlookup;
-		ctx->lookup_index = nindex;
-		ctx->lookup_size = nsize;
-	}
-	int pos = (min + max) >> 1;
-	memmove(ctx->lookup + pos + 1, ctx->lookup + pos, (ctx->lookup_pos - pos) * sizeof(void*));
-	memmove(ctx->lookup_index + pos + 1, ctx->lookup_index + pos, (ctx->lookup_pos - pos) * sizeof(int));
-	int id = ctx->lookup_pos++;
-	ctx->lookup[pos] = addr;
-	ctx->lookup_index[pos] = id | (is_bytes ? BYTE_MARK : 0);
+	int *v = hl_mlookup_find(ctx->lookup, addr);
+	if( v )
+		return ctx->remap_target[(*v)&~BYTE_MARK];
+	int id = ctx->remap_pos;
+	hl_mlookup_set_impl(ctx->lookup, addr, id | (is_bytes ? BYTE_MARK : 0));
 	compact_grow(todos,todos_pos,todos_size,1,void*);
 	ctx->todos[ctx->todos_pos++] = addr;
 	compact_grow(remap_target,remap_pos,remap_size,1,int);
 	int target = -id-1;
-	ctx->remap_target[ctx->remap_pos++] = target;
+	ctx->remap_target[id] = target;
+	ctx->remap_pos++;
 	return target;
 }
 
@@ -908,6 +879,7 @@ HL_PRIM vdynamic *hl_mem_compact( vdynamic *d, varray *exclude, int flags, int *
 	int i;
 	int object_count = 0;
 	memset(ctx,0,sizeof(mem_context));
+	ctx->lookup = hl_mlookup_alloc();
 	ctx->flags = flags;
 	compact_lookup_ref(ctx,d,false);
 	if( exclude ) {
@@ -919,8 +891,7 @@ HL_PRIM vdynamic *hl_mem_compact( vdynamic *d, varray *exclude, int flags, int *
 	}
 	while( ctx->todos_pos > 0 ) {
 		void *addr = ctx->todos[--ctx->todos_pos];
-		int pos = compact_lookup_index(ctx, addr);
-		int index = ctx->lookup_index[pos];
+		int index = *hl_mlookup_find(ctx->lookup, addr);
 		compact_pad(ctx, &hlt_dyn);
 		ctx->remap_target[index&~BYTE_MARK] = ctx->buf_pos;
 		if( index & BYTE_MARK ) {
@@ -955,8 +926,6 @@ HL_PRIM vdynamic *hl_mem_compact( vdynamic *d, varray *exclude, int flags, int *
 	}
 	free(ctx->buf);
 	free(ctx->offsets);
-	free(ctx->lookup);
-	free(ctx->lookup_index);
 	free(ctx->remap_target);
 	free(ctx->todos);
 #	ifdef HL_WIN