[前][次][番号順一覧][スレッド一覧]

ruby-changes:5514

From: ko1 <ko1@a...>
Date: Sun, 8 Jun 2008 19:27:21 +0900 (JST)
Subject: [ruby-changes:5514] Ruby:r17018 (trunk): * gc.c: add a build option "CALC_EXACT_MALLOC_SIZE".

ko1	2008-06-08 19:27:06 +0900 (Sun, 08 Jun 2008)

  New Revision: 17018

  Modified files:
    trunk/ChangeLog
    trunk/gc.c

  Log:
    * gc.c: add a build option "CALC_EXACT_MALLOC_SIZE".
      This option enables to calculate exact size of current
      allocated size by malloc().  You can access these information
      with GC.malloc_allocated_size and GC.malloc_allocations.
      This option consume additional memory as a header of each memory
      object.  This option also helps to find out xmalloc()/xfree()
      consistency.  If you get trouble with this option, some extension
      using "free()" instead of "xfree()".
      This options is disabled by default.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17018&r2=17017&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/gc.c?r1=17018&r2=17017&diff_format=u

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17017)
+++ ChangeLog	(revision 17018)
@@ -1,3 +1,15 @@
+Sun Jun  8 19:17:59 2008  Koichi Sasada  <ko1@a...>
+
+	* gc.c: add a build option "CALC_EXACT_MALLOC_SIZE".
+	  This option enables to calculate exact size of current 
+	  allocated size by malloc().  You can access these information
+	  with GC.malloc_allocated_size and GC.malloc_allocations.
+	  This option consume additional memory as a header of each memory
+	  object.  This option also helps to find out xmalloc()/xfree()
+	  consistency.  If you get trouble with this option, some extension
+	  using "free()" instead of "xfree()".
+	  This options is disabled by default.
+
 Sun Jun  8 18:15:38 2008  Koichi Sasada  <ko1@a...>
 
 	* array.c, bignum.c, cont.c, dir.c, dln.c, encoding.c, enumerator.c,
Index: gc.c
===================================================================
--- gc.c	(revision 17017)
+++ gc.c	(revision 17018)
@@ -143,11 +143,17 @@
     struct gc_list *next;
 };
 
+#define CALC_EXACT_MALLOC_SIZE 0
+
 typedef struct rb_objspace {
     struct {
 	size_t limit;
 	size_t increase;
-    } params;
+#if CALC_EXACT_MALLOC_SIZE
+	size_t allocated_size;
+	size_t allocations;
+#endif
+    } malloc_params;
     struct {
 	size_t increment;
 	struct heaps_slot *ptr;
@@ -180,8 +186,8 @@
 #else
 static rb_objspace_t rb_objspace = {{GC_MALLOC_LIMIT}, {HEAP_MIN_SLOTS}};
 #endif
-#define malloc_limit		objspace->params.limit
-#define malloc_increase 	objspace->params.increase
+#define malloc_limit		objspace->malloc_params.limit
+#define malloc_increase 	objspace->malloc_params.increase
 #define heap_slots		objspace->heap.slots
 #define heaps			objspace->heap.ptr
 #define heaps_length		objspace->heap.length
@@ -307,8 +313,8 @@
     return bool;
 }
 
-void *
-ruby_vm_xmalloc(rb_objspace_t *objspace, size_t size)
+static void *
+vm_xmalloc(rb_objspace_t *objspace, size_t size)
 {
     void *mem;
 
@@ -317,6 +323,10 @@
     }
     if (size == 0) size = 1;
 
+#if CALC_EXACT_MALLOC_SIZE
+    size += sizeof(size_t);
+#endif
+
     if (ruby_gc_stress || (malloc_increase+size) > malloc_limit) {
 	garbage_collect(objspace);
     }
@@ -331,51 +341,19 @@
     }
     malloc_increase += size;
 
-    return mem;
-}
+#if CALC_EXACT_MALLOC_SIZE
+    objspace->malloc_params.allocated_size += size;
+    objspace->malloc_params.allocations++;
+    ((size_t *)mem)[0] = size;
+    mem = (size_t *)mem + 1;
+#endif
 
-void *
-ruby_xmalloc(size_t size)
-{
-    return ruby_vm_xmalloc(&rb_objspace, size);
-}
-
-void *
-ruby_vm_xmalloc2(rb_objspace_t *objspace, size_t n, size_t size)
-{
-    size_t len = size * n;
-    if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "malloc: possible integer overflow");
-    }
-    return ruby_vm_xmalloc(objspace, len);
-}
-
-void *
-ruby_xmalloc2(size_t n, size_t size)
-{
-    return ruby_vm_xmalloc2(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xcalloc(rb_objspace_t *objspace, size_t n, size_t size)
-{
-    void *mem;
-
-    mem = ruby_vm_xmalloc2(objspace, n, size);
-    memset(mem, 0, n * size);
-
     return mem;
 }
 
-void *
-ruby_xcalloc(size_t n, size_t size)
+static void *
+vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
 {
-    return ruby_vm_xcalloc(&rb_objspace, n, size);
-}
-
-void *
-ruby_vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t size)
-{
     void *mem;
 
     if (size < 0) {
@@ -384,6 +362,13 @@
     if (!ptr) return ruby_xmalloc(size);
     if (size == 0) size = 1;
     if (ruby_gc_stress) garbage_collect(objspace);
+
+#if CALC_EXACT_MALLOC_SIZE
+    size += sizeof(size_t);
+    objspace->malloc_params.allocated_size -= size;
+    ptr = (size_t *)ptr - 1;
+#endif
+
     RUBY_CRITICAL(mem = realloc(ptr, size));
     if (!mem) {
 	if (garbage_collect(objspace)) {
@@ -395,36 +380,75 @@
     }
     malloc_increase += size;
 
+#if CALC_EXACT_MALLOC_SIZE
+    objspace->malloc_params.allocated_size += size;
+    ((size_t *)mem)[0] = size;
+    mem = (size_t *)mem + 1;
+#endif
+
     return mem;
 }
 
+static void
+vm_xfree(rb_objspace_t *objspace, void *ptr)
+{
+#if CALC_EXACT_MALLOC_SIZE
+    size_t size;
+    ptr = ((size_t *)ptr) - 1;
+    size = ((size_t*)ptr)[0];
+    objspace->malloc_params.allocated_size -= size;
+    objspace->malloc_params.allocations--;
+#endif
+
+    RUBY_CRITICAL(free(ptr));
+}
+
 void *
-ruby_xrealloc(void *ptr, size_t size)
+ruby_xmalloc(size_t size)
 {
-    return ruby_vm_xrealloc(&rb_objspace, ptr, size);
+    return vm_xmalloc(&rb_objspace, size);
 }
 
 void *
-ruby_vm_xrealloc2(rb_objspace_t *objspace, void *ptr, size_t n, size_t size)
+ruby_xmalloc2(size_t n, size_t size)
 {
     size_t len = size * n;
     if (n != 0 && size != len / n) {
-	rb_raise(rb_eArgError, "realloc: possible integer overflow");
+	rb_raise(rb_eArgError, "malloc: possible integer overflow");
     }
-    return ruby_vm_xrealloc(objspace, ptr, len);
+    return vm_xmalloc(&rb_objspace, len);
 }
 
 void *
+ruby_xcalloc(size_t n, size_t size)
+{
+    void *mem = ruby_xmalloc2(n, size);
+    memset(mem, 0, n * size);
+
+    return mem;
+}
+
+void *
+ruby_xrealloc(void *ptr, size_t size)
+{
+    return vm_xrealloc(&rb_objspace, ptr, size);
+}
+
+void *
 ruby_xrealloc2(void *ptr, size_t n, size_t size)
 {
-    return ruby_vm_xrealloc2(&rb_objspace, ptr, n, size);
+    size_t len = size * n;
+    if (n != 0 && size != len / n) {
+	rb_raise(rb_eArgError, "realloc: possible integer overflow");
+    }
+    return ruby_xrealloc(ptr, len);
 }
 
 void
 ruby_xfree(void *x)
 {
     if (x)
-	RUBY_CRITICAL(free(x));
+      vm_xfree(&rb_objspace, x);
 }
 
 
@@ -2377,7 +2401,39 @@
     return UINT2NUM((&rb_objspace)->count);
 }
 
+#if CALC_EXACT_MALLOC_SIZE
 /*
+ *  call-seq:
+ *     GC.malloc_allocated_size -> Integer
+ *
+ *  The allocated size by malloc().
+ *
+ *  It returns the allocated size by malloc().
+ */
+
+static VALUE
+gc_malloc_allocated_size(VALUE self)
+{
+    return UINT2NUM((&rb_objspace)->malloc_params.allocated_size);
+}
+
+/*
+ *  call-seq:
+ *     GC.malloc_allocations -> Integer
+ *
+ *  The number of allocated memory object by malloc().
+ *
+ *  It returns the number of allocated memory object by malloc().
+ */
+
+static VALUE
+gc_malloc_allocations(VALUE self)
+{
+    return UINT2NUM((&rb_objspace)->malloc_params.allocations);
+}
+#endif
+
+/*
  *  The <code>GC</code> module provides an interface to Ruby's mark and
  *  sweep garbage collection mechanism. Some of the underlying methods
  *  are also available via the <code>ObjectSpace</code> module.
@@ -2414,4 +2470,9 @@
     rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
 
     rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
+
+#if CALC_EXACT_MALLOC_SIZE
+    rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
+    rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
+#endif
 }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]