[#34011] Should --verbose be equal to -v ? — Yugui <yugui@...>

Yuguiです。

15 messages 2008/03/10
[#34012] Re: Should --verbose be equal to -v ? — Yukihiro Matsumoto <matz@...> 2008/03/10

まつもと ゆきひろです

[#34105] rational.rb, complex.rb and mathn.rb — Tadayoshi Funaba <tadf@...>

rational と complex が組み込みになったことで、lib/mathn.rb の意義は薄

29 messages 2008/03/22
[#34106] Re: rational.rb, complex.rb and mathn.rb — Tadayoshi Funaba <tadf@...> 2008/03/22

現時点で rational.rb と complex.rb を残しているのは、それが無難だから

[#34107] Re: rational.rb, complex.rb and mathn.rb — Tadayoshi Funaba <tadf@...> 2008/03/22

で、かなり選択肢を絞った叩き台です。

[#34120] Re: rational.rb, complex.rb and mathn.rb — keiju@... (石塚圭樹) 2008/03/24

けいじゅ@いしつかです.

[#34125] Re: rational.rb, complex.rb and mathn.rb — Shin-ichiro HARA <sinara@...> 2008/03/25

原です。

[#34130] Re: rational.rb, complex.rb and mathn.rb — Tadayoshi Funaba <tadf@...> 2008/03/25

> 私も Complex の組み込みは Rational とは比較にならないくらい、仕様が決め

[#34158] Complex組み込み — Masahiro TANAKA <masa16.tanaka@...>

Complexが組み込みになるそうですが、これはcomplex.rbを踏襲して、

49 messages 2008/03/27
[#34161] Re: Complex組み込み — Shin-ichiro HARA <sinara@...> 2008/03/28

原です。

[#34168] Re: Complex組み込み — Tadayoshi Funaba <tadf@...> 2008/03/28

> 今までの Complex は、complex.rb にほぼ残して、たとえば Rational 成分

[#34186] Re: Complex組み込み — Shin-ichiro HARA <sinara@...> 2008/03/31

原です。

[#34187] Re: Complex組み込み — Tadayoshi Funaba <tadf@...> 2008/03/31

> そうです。Complex が難しい、という話を書いておくと、

[#34193] Re: Complex組み込み — Yukihiro Matsumoto <matz@...> 2008/03/31

まつもと ゆきひろです

[#34203] Re: Complex組み込み — Tadayoshi Funaba <tadf@...> 2008/04/01

> |僕としては、/ 演算子の振舞いについて前向きに検討してほしいです。

[#34215] Re: Complex組み込み — Yukihiro Matsumoto <matz@...> 2008/04/02

まつもと ゆきひろです

[#34166] Re: Complex組み込み — Tadayoshi Funaba <tadf@...> 2008/03/28

> となるようですが、別の実装として、

[ruby-dev:34022] patch of lazy sweep gc

From: authorNari <authornari@...>
Date: 2008-03-11 14:01:21 UTC
List: ruby-dev #34022
初めまして、中村と申します。

RubyGCにLazySweepを取り込んだものを作ってみました。
パッチは添付しています。

詳細は
http://d.hatena.ne.jp/authorNari/20080311/1205242360
に書いております。

あまり性能が劇的に改善されているわけではないのですが、
中々苦労しましたので、一応ご報告させていただきました。(^_^;)

何かの参考になれば幸いです。

--
id:authorNari

Attachments (1)

gc_lazy_sweep_r15749_patch.diff (11.5 KB, text/x-diff)
Index: gc.c
===================================================================
--- gc.c	($B%j%S%8%g%s(B 15749)
+++ gc.c	($B:n6H%3%T!<(B)
@@ -11,6 +11,7 @@
 
 **********************************************************************/
 
+
 #include "ruby/ruby.h"
 #include "ruby/signal.h"
 #include "ruby/st.h"
@@ -131,6 +132,7 @@
     char *file;
     int   line;
 #endif
+    char color;
 } RVALUE;
 
 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
@@ -140,6 +142,25 @@
 static RVALUE *freelist = 0;
 static RVALUE *deferred_final_list = 0;
 
+/* lazy sweep */
+static int gc_state = 0;
+static int lazy_sweeps_lenght = 0;
+static int sweep_time = 0;
+static int sweeping_slot = 0;
+static int end_sweep_slot = 0;
+static unsigned long lazy_lease_limit = 0;
+static unsigned long lazy_lease_rest = 0;
+static struct heaps_slot *heaps_sort_limit = 0;
+static int heaps_sort_limit_used = 0;
+static int *lazy_brancer = 0;
+static int heap_update = 0;
+#define WHITE 0
+#define BLACK 1
+#define NORMAL_SWEEP_LIMIT 1000000
+//#define NORMAL_SWEEP_LIMIT 0
+#define GC_STATE_NORMAL 0
+#define GC_STATE_LAZY_SWEEP 1
+
 #define HEAPS_INCREMENT 10
 static struct heaps_slot {
     void *membase;
@@ -148,6 +169,7 @@
 } *heaps;
 static int heaps_length = 0;
 static int heaps_used   = 0;
+static int heaps_objs = 0;
 
 #define HEAP_MIN_SLOTS 10000
 static int heap_slots = HEAP_MIN_SLOTS;
@@ -181,6 +203,7 @@
 static void run_final(VALUE obj);
 static int garbage_collect(void);
 
+
 void
 rb_global_variable(VALUE *var)
 {
@@ -435,6 +458,12 @@
 		p = heaps = (struct heaps_slot *)malloc(length);
 	    });
 	if (p == 0) rb_memerror();
+	if (!heaps_sort_limit)
+	    heaps_sort_limit = malloc(length);
+	else
+	    heaps_sort_limit = realloc(heaps_sort_limit, length);
+	if (!heaps_sort_limit)
+	    rb_memerror();
     }
 
     for (;;) {
@@ -484,13 +513,24 @@
     heap_slots *= 1.8;
 
     while (p < pend) {
+	p->color = WHITE;
 	p->as.free.flags = 0;
 	p->as.free.next = freelist;
 	freelist = p;
 	p++;
     }
+
+    //lazy_sweep
+    int i = 0;
+    heaps_objs = 0;
+    for (i = 0; i < heaps_used; i++) {
+	heaps_objs += heaps[i].limit;
+    }
+    heaps_sort_limit[heaps_sort_limit_used] = heaps[hi];
+    heaps_sort_limit_used++;
+    heap_update = 1;
+
 }
-
 #define RANY(o) ((RVALUE*)(o))
 
 static VALUE
@@ -504,10 +544,25 @@
 	}
     }
 
+    //lazy sweep
+    if (lazy_lease_limit) {
+	if (!lazy_lease_rest) {
+	    lazy_lease_rest = lazy_lease_limit;
+	    if (!garbage_collect()) {
+		rb_memerror();
+	    }
+	}
+	lazy_lease_rest--;
+    }
+    
     obj = (VALUE)freelist;
     freelist = freelist->as.free.next;
 
+    /* flags keep */
+    char c = RANY(obj)->color;
     MEMZERO((void*)obj, RVALUE, 1);
+    RANY(obj)->color = c;
+
 #ifdef GC_DEBUG
     RANY(obj)->file = rb_sourcefile();
     RANY(obj)->line = rb_sourceline();
@@ -528,6 +583,7 @@
 	
 	th->value_cache[i] = v;
 	RBASIC(v)->flags = FL_MARK;
+	RANY(v)->color = BLACK;
     }
     th->value_cache_ptr = &th->value_cache[0];
     rv = rb_newobj_from_heap();
@@ -545,6 +601,7 @@
 
     if (v) {
 	RBASIC(v)->flags = 0;
+	RANY(v)->color = WHITE;
 	th->value_cache_ptr++;
     }
     else {
@@ -716,8 +773,8 @@
     for (i = 0; i < heaps_used; i++) {
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
-	    if ((p->as.basic.flags & FL_MARK) &&
-		(p->as.basic.flags != FL_MARK)) {
+	    if ((p->color & BLACK) &&
+		(p->as.free.flags != FL_MARK)) {
 		gc_mark_children((VALUE)p, 0);
 	    }
 	    p++;
@@ -871,8 +928,8 @@
     obj = RANY(ptr);
     if (rb_special_const_p(ptr)) return; /* special const not marked */
     if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
+    if (obj->color & BLACK) return;  /* already marked */
+    obj->color = BLACK;
 
     if (lev > GC_LEVEL_MAX || (lev == 0 && ruby_stack_check())) {
 	if (!mark_stack_overflow) {
@@ -905,9 +962,9 @@
   again:
     obj = RANY(ptr);
     if (rb_special_const_p(ptr)) return; /* special const not marked */
-    if (obj->as.basic.flags == 0) return;       /* free cell */
-    if (obj->as.basic.flags & FL_MARK) return;  /* already marked */
-    obj->as.basic.flags |= FL_MARK;
+    if (obj->as.free.flags == 0) return;       /* free cell */
+    if (obj->color & BLACK) return;  /* already marked */
+    obj->color = BLACK;
 
   marking:
     if (FL_TEST(obj, FL_EXIVAR)) {
@@ -1099,8 +1156,8 @@
 
       case T_OBJECT:
         {
-            long i, len = ROBJECT_NUMIV(obj);
-	    VALUE *ptr = ROBJECT_IVPTR(obj);
+	     long i, len = ROBJECT_NUMIV(obj);
+ 	    VALUE *ptr = ROBJECT_IVPTR(obj);
             for (i  = 0; i < len; i++) {
 		gc_mark(*ptr++, lev);
             }
@@ -1163,6 +1220,7 @@
 	run_final((VALUE)p);
 	if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
             VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+	    p->color = WHITE;
 	    p->as.free.flags = 0;
 	    p->as.free.next = freelist;
 	    freelist = p;
@@ -1222,7 +1280,7 @@
 
 	p = heaps[i].slot; pend = p + heaps[i].limit;
 	while (p < pend) {
-	    if (!(p->as.basic.flags & FL_MARK)) {
+	    if (p->color != BLACK) {
 		if (p->as.basic.flags) {
 		    obj_free((VALUE)p);
 		}
@@ -1233,6 +1291,7 @@
 		}
 		else {
                     VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+		    p->color = WHITE;
 		    p->as.free.flags = 0;
 		    p->as.free.next = freelist;
 		    freelist = p;
@@ -1244,7 +1303,7 @@
 		/* do nothing remain marked */
 	    }
 	    else {
-		RBASIC(p)->flags &= ~FL_MARK;
+		p->color = WHITE;
 		live++;
 	    }
 	    p++;
@@ -1280,11 +1339,150 @@
     free_unused_heaps();
 }
 
+static void
+init_lazy_sweep(void) {
+    int i, e, n = 0;
+
+    if (heaps_sort_limit_used > heaps_used) {
+	for (i = 0; i < heaps_sort_limit_used; i++) {
+	    if (!heaps_sort_limit[i].limit) {
+		MEMMOVE(&heaps_sort_limit[i+1], &heaps_sort_limit[i], struct heaps_slot, heaps_sort_limit_used-i-1);
+		heaps_sort_limit_used--;
+	    heap_update = 1;
+	    }
+	}
+    }
+    
+    if (!lazy_brancer)
+	lazy_brancer = malloc(sizeof(int)*heaps_length);
+    else if (heaps_used >= heaps_length)
+	lazy_brancer = realloc(lazy_brancer, sizeof(int) * heaps_length);
+    if (!lazy_brancer)
+	rb_memerror();
+	
+	if(heap_update) {
+    for (i = 0; i < heaps_sort_limit_used; i++) {
+	e = heaps_sort_limit_used - n - 1;
+	lazy_brancer[i] = n;
+	if (n >= e)
+	    break;
+	lazy_brancer[++i] = e;
+	n++;
+    }
+		heap_update = 0;
+	}
+
+    sweeping_slot = 0;
+    end_sweep_slot = heaps_sort_limit_used;
+    sweep_time = heaps_sort_limit_used * 0.25;
+    if (!sweep_time) sweep_time = 1;
+
+    gc_state = GC_STATE_LAZY_SWEEP;
+}
+
+static void
+gc_lazy_sweep(void) {
+    RVALUE *p, *pend, *final_list;
+    int freed = 0, i =0, free_min = 0;
+    unsigned long live = 0;
+
+    if (gc_state == GC_STATE_NORMAL) {
+	init_lazy_sweep();
+	if (source_filenames)
+	    st_foreach(source_filenames, sweep_source_filename, 0);
+	if (freelist) {
+	    during_gc = 0;
+	    return;
+	}
+    }
+    
+    final_list = deferred_final_list;
+    deferred_final_list = 0;
+
+    for (i = 0; i < sweep_time; i++) {
+	int n = 0;
+	int b = lazy_brancer[sweeping_slot];
+	RVALUE *free = freelist;
+	RVALUE *final = final_list;
+
+	p = heaps_sort_limit[b].slot; pend = p + heaps_sort_limit[b].limit;
+	while (p < pend) {
+	    if (p->color != BLACK) {
+		if (RBASIC(p)->flags) {
+		    obj_free((VALUE)p);
+		}
+		if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+		    p->as.free.flags = FL_MARK; /* remain marked */
+		    p->as.free.next = final_list;
+		    final_list = p;
+		}
+		else if (RBASIC(p)->flags) {
+		    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+		    p->color = WHITE;
+		    p->as.free.flags = 0;
+		    p->as.free.next = freelist;
+		    freelist = p;
+		}
+		n++;
+	    }
+	    else if (RBASIC(p)->flags != FL_MARK) {
+		p->color = WHITE;
+		live++;
+	    }
+	    p++;
+	}
+	
+	if (n == heaps_sort_limit[b].limit) {
+	    RVALUE *pp;
+	    heaps_sort_limit[b].limit = 0;
+	    for (pp = final_list; pp != final; pp = pp->as.free.next) p->as.free.flags |= FL_SINGLETON;
+	    freelist = free;
+	}
+	else {
+	    freed += n;
+	}
+	sweeping_slot++;
+	if (sweeping_slot >= end_sweep_slot)
+	    break;
+    }
+
+    if (malloc_increase > malloc_limit) {
+ 	malloc_limit += (malloc_increase - malloc_limit) * ((double)live / (live + freed) / end_sweep_slot);
+ 	if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
+    }
+	
+    if (!freelist) {
+	heap_slots = heap_slots * 0.7;
+	add_heap();
+	lazy_lease_limit = heaps_sort_limit[heaps_sort_limit_used-1].limit * 0.20;
+	lazy_lease_rest = lazy_lease_limit;
+    }
+
+    if (sweeping_slot >= end_sweep_slot) { 
+	end_sweep_slot = 0;
+	sweeping_slot = 0;
+    	malloc_increase = 0;
+	gc_state = GC_STATE_NORMAL;
+    }
+
+    during_gc = 0;
+
+    /* clear finalization list */
+    if (final_list) {
+    	deferred_final_list = final_list;
+    	return;
+    }
+	
+    if (!sweeping_slot) free_unused_heaps();
+}
+
 void
 rb_gc_force_recycle(VALUE p)
 {
     VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
     RANY(p)->as.free.flags = 0;
+    if (!(gc_state == GC_STATE_LAZY_SWEEP && RANY(p)->color == BLACK))
+    	RANY(p)->color = WHITE;
     RANY(p)->as.free.next = freelist;
     freelist = RANY(p);
 }
@@ -1493,25 +1691,23 @@
 
 void rb_gc_mark_encodings(void);
 
-static int
-garbage_collect(void)
+static void
+rb_mark_freelist(void)
 {
-    struct gc_list *list;
-    rb_thread_t *th = GET_THREAD();
+    RVALUE *p = freelist;
+    while(p) {
+	p->color = BLACK;
+	p = p->as.free.next;
+    }
+}
 
-    if (GC_NOTIFY) printf("start garbage_collect()\n");
 
-    if (!heaps) {
-	return Qfalse;
-    }
 
-    if (dont_gc || during_gc) {
-	if (!freelist) {
-	    add_heap();
-	}
-	return Qtrue;
-    }
-    during_gc++;
+static void
+gc_marks(void)
+{
+    struct gc_list *list;
+    rb_thread_t *th = GET_THREAD();
 
     SET_STACK_END;
 
@@ -1554,11 +1750,73 @@
 	}
     }
 
+}
+
+static int 
+mark_and_sweep(void)
+{
+    if (!heaps) {
+	return Qfalse;
+    }
+
+    if (dont_gc || during_gc) {
+	if (!freelist) {
+	    add_heap();
+	}
+	return Qtrue;
+    }
+    during_gc++;
+
+    if (gc_state == GC_STATE_LAZY_SWEEP) {
+	gc_state = GC_STATE_NORMAL;
+	lazy_lease_limit = 0;
+	lazy_lease_rest = 0;
+    }    
+
+    gc_marks();
+	
     gc_sweep();
-    if (GC_NOTIFY) printf("end garbage_collect()\n");
+	
     return Qtrue;
 }
 
+static int
+mark_and_lazy_sweep(void)
+{
+
+    if (!heaps) {
+	return Qfalse;
+    }
+
+    if (dont_gc || during_gc) {
+	if (!freelist) {
+	    add_heap();
+	}
+	return Qtrue;
+    }
+    during_gc++;
+    if (gc_state == GC_STATE_NORMAL) {
+	gc_marks();
+	if (freelist)
+	    rb_mark_freelist();
+    }
+	
+    gc_lazy_sweep();
+	
+    return Qtrue;
+}
+
+static int
+garbage_collect(void)
+{
+    if (heaps_objs > NORMAL_SWEEP_LIMIT)
+	return mark_and_lazy_sweep();
+
+    return mark_and_sweep();
+}
+
+
+
 int
 rb_garbage_collect(void)
 {
@@ -2017,7 +2275,7 @@
     if (p) {
 	finalize_list(p);
     }
-    free_unused_heaps();
+    if(!sweeping_slot) free_unused_heaps();
     during_gc = 0;
 }
 
@@ -2054,6 +2312,7 @@
 		DATA_PTR(p) && RANY(p)->as.data.dfree &&
 		RANY(p)->as.basic.klass != rb_cThread) {
 		p->as.free.flags = 0;
+		p->color = WHITE;
 		if ((long)RANY(p)->as.data.dfree == -1) {
 		    RUBY_CRITICAL(free(DATA_PTR(p)));
 		}
@@ -2065,6 +2324,7 @@
 	    else if (BUILTIN_TYPE(p) == T_FILE) {
 		if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
 		    p->as.free.flags = 0;
+		    p->color = WHITE;
                     VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
 		}
 	    }

In This Thread

Prev Next