[#53097] [ruby-trunk - Bug #8000][Open] "require 'tk'" segfaults on 64-bit linux with Tk 8.6 — "edmccard (Ed McCardell)" <edmccard@...>
25 messages
2013/03/02
[#53199] [ruby-trunk - Bug #8040][Open] Unexpect behavior when using keyword arguments — "pabloh (Pablo Herrero)" <pablodherrero@...>
11 messages
2013/03/07
[#53203] [ruby-trunk - Feature #8042][Open] Add Addrinfo#socket to create a socket that is not connected or bound — "drbrain (Eric Hodel)" <drbrain@...7.net>
12 messages
2013/03/07
[#55610] [ruby-trunk - Feature #8042] Add Addrinfo#socket to create a socket that is not connected or bound
— "headius (Charles Nutter)" <headius@...>
2013/06/23
[#53211] [ruby-trunk - Feature #8046][Open] allow Object#extend to take a block — "phluid61 (Matthew Kerwin)" <matthew@...>
6 messages
2013/03/08
[#53248] Github commit log should not be used as references on redmine — Marc-Andre Lafortune <ruby-core-mailing-list@...>
Github commit log should not be used as references on redmine. E.g:
10 messages
2013/03/09
[#53249] Re: Github commit log should not be used as references on redmine
— Zachary Scott <zachary@...>
2013/03/09
I think redmine should ignore flags like \[GH.*#\d*\] or something similar.
[#53606] Re: Github commit log should not be used as references on redmine
— Zachary Scott <zachary@...>
2013/03/21
Ping!
[#53615] Re: Github commit log should not be used as references on redmine
— "NARUSE, Yui" <naruse@...>
2013/03/22
The best place of creating Feature Requests for bug.ruby-lang.org's Redmine
[#53265] [ruby-trunk - Bug #8058][Open] RubyGems test failures under MinGW — "luislavena (Luis Lavena)" <luislavena@...>
5 messages
2013/03/09
[#53349] [ruby-trunk - Bug #8080][Open] Segfault in rb_fd_set — "jonleighton (Jon Leighton)" <j@...>
8 messages
2013/03/12
[#53386] [CommonRuby - Feature #8088][Open] Method#parameters (and friends) should provide useful information about core methods — "headius (Charles Nutter)" <headius@...>
14 messages
2013/03/13
[#55921] [CommonRuby - Feature #8088] Method#parameters (and friends) should provide useful information about core methods
— "headius (Charles Nutter)" <headius@...>
2013/07/10
[#55922] Re: [CommonRuby - Feature #8088] Method#parameters (and friends) should provide useful information about core methods
— Yorick Peterse <yorickpeterse@...>
2013/07/10
Consider the following code:
[#55926] Re: [CommonRuby - Feature #8088] Method#parameters (and friends) should provide useful information about core methods
— Charles Oliver Nutter <headius@...>
2013/07/10
On Wed, Jul 10, 2013 at 11:16 AM, Yorick Peterse
[#53412] [CommonRuby - Feature #8096][Open] introduce Time.current_timestamp — "vipulnsward (Vipul Amler)" <vipulnsward@...>
34 messages
2013/03/14
[#53461] [CommonRuby - Feature #8096] introduce Time.current_timestamp
— "vipulnsward (Vipul Amler)" <vipulnsward@...>
2013/03/15
[#53478] [ruby-trunk - Feature #8107][Open] [patch] runtime flag to track object allocation metadata — "tmm1 (Aman Gupta)" <ruby@...1.net>
20 messages
2013/03/16
[#53526] [ruby-trunk - Feature #8107] [patch] runtime flag to track object allocation metadata
— "tmm1 (Aman Gupta)" <ruby@...1.net>
2013/03/19
[#53523] [ruby-trunk - Bug #8122][Open] [patch] gc: GC.stat improvements and related cleanup — "tmm1 (Aman Gupta)" <ruby@...1.net>
5 messages
2013/03/19
[#53585] Consistent hashing in the face of HashDOS? — Charles Oliver Nutter <headius@...>
It had to happen eventually...
7 messages
2013/03/21
[#53599] [Backport 200 - Backport #8135][Open] Backport escape all closing parens - r39858 — "vo.x (Vit Ondruch)" <v.ondruch@...>
7 messages
2013/03/21
[#53619] [ruby-trunk - Bug #8142][Open] [patch] iseq: reduce array allocations for simple sequences — "tmm1 (Aman Gupta)" <ruby@...1.net>
7 messages
2013/03/22
[#53635] [ruby-trunk - Bug #8148][Open] [patch] reduce allocations due to __FILE__ and {class,module}_eval — "tmm1 (Aman Gupta)" <ruby@...1.net>
6 messages
2013/03/22
[#54391] [ruby-trunk - Bug #8148] [patch] reduce allocations due to __FILE__ and {class,module}_eval
— "headius (Charles Nutter)" <headius@...>
2013/04/17
[#53679] Why doesn’t String#+ return an untrusted result if self or other is untrusted? — Nikolai Weibull <now@...>
Hi!
5 messages
2013/03/23
[#53680] Re: [ruby-core:53679] Why doesn’t String#+ return an untrusted result if self or other is untrusted?
— KOSAKI Motohiro <kosaki.motohiro@...>
2013/03/23
On Sat, Mar 23, 2013 at 2:45 PM, Nikolai Weibull <now@bitwi.se> wrote:
[#53685] Re: [ruby-core:53680] Re: [ruby-core:53679] Why doesn’t String#+ return an untrusted result if self or other is untrusted?
— Nikolai Weibull <now@...>
2013/03/23
On Sat, Mar 23, 2013 at 8:30 PM, KOSAKI Motohiro
[#53688] [ruby-trunk - Feature #8158][Open] lightweight structure for loaded features index — "funny_falcon (Yura Sokolov)" <funny.falcon@...>
27 messages
2013/03/24
[#53692] [ruby-trunk - Bug #8159][Open] Build failure introduced by Rinda changes — "luislavena (Luis Lavena)" <luislavena@...>
22 messages
2013/03/24
[#53713] [ruby-trunk - Bug #8159] Build failure introduced by Rinda changes
— "naruse (Yui NARUSE)" <naruse@...>
2013/03/25
[#53709] [Backport 200 - Backport #8163][Assigned] Backport r39919 — "authorNari (Narihiro Nakamura)" <authorNari@...>
6 messages
2013/03/25
[#53733] [ruby-trunk - Bug #8165][Open] Problems with require — "Krugloff (Alexandr Kruglov)" <mr.krugloff@...>
12 messages
2013/03/26
[#53764] [ruby-trunk - Bug #8173][Open] 2-arg form of Time.at can take a Time as either argument — "hasari (Hiro Asari)" <asari.ruby@...>
8 messages
2013/03/27
[#53808] [ruby-trunk - Feature #8181][Open] New flag for strftime that supports adding ordinal suffixes to numbers — "tkellen (Tyler Kellen)" <tyler@...>
10 messages
2013/03/28
[#53811] [ruby-trunk - Bug #8182][Open] XMLRPC request fails with "Wrong size. Was 31564, should be 1501" — "tsagadar (Marcel Mueller)" <marcel.mueller@...>
28 messages
2013/03/28
[#53825] Thread/fork issue — Jason Gladish <jason@...>
Hello all,
9 messages
2013/03/29
[#53832] Re: Thread/fork issue
— Tanaka Akira <akr@...>
2013/03/29
2013/3/30 Jason Gladish <jason@expectedbehavior.com>:
[#53887] Re: Thread/fork issue
— Tanaka Akira <akr@...>
2013/04/02
2013/3/30 Tanaka Akira <akr@fsij.org>:
[#53901] Re: Thread/fork issue
— KOSAKI Motohiro <kosaki.motohiro@...>
2013/04/02
> I wrote a simple script to reproduce the problem.
[#53849] [ruby-trunk - Feature #8191][Open] Short-hand syntax for duck-typing — "wardrop (Tom Wardrop)" <tom@...>
48 messages
2013/03/31
[#53894] [ruby-trunk - Feature #8191] Short-hand syntax for duck-typing
— "rosenfeld (Rodrigo Rosenfeld Rosas)" <rr.rosas@...>
2013/04/02
[#53938] [ruby-trunk - Feature #8191] Short-hand syntax for duck-typing
— "phluid61 (Matthew Kerwin)" <matthew@...>
2013/04/03
[#53916] [ruby-trunk - Feature #8191] Short-hand syntax for duck-typing
— "wardrop (Tom Wardrop)" <tom@...>
2013/04/03
[#53850] An evaluation of 2.0.0 release — Yusuke Endoh <mame@...>
Let's look back at 2.0.0 release so that we can do better next time.
12 messages
2013/03/31
[#53853] Re: An evaluation of 2.0.0 release
— V咜 Ondruch <v.ondruch@...>
2013/03/31
Hello Yusuke,
[ruby-core:53534] [ruby-trunk - Feature #8107] [patch] runtime flag to track object allocation metadata
From:
"tmm1 (Aman Gupta)" <ruby@...1.net>
Date:
2013-03-19 06:45:46 UTC
List:
ruby-core #53534
Issue #8107 has been updated by tmm1 (Aman Gupta).
> Using this APIs, users can add your own statistics libraries.
I tried a similar approach in ruby 1.8 some while ago, emulating event hook api for GC events (newobj, free, gc start/end): https://github.com/tmm1/brew2deb/blob/master/packages/ruby/patches/gc-hooks.patch
I agree this approach provides more flexibility. But GC hooks cannot allocate ruby objects or interact with GC, so it is tricky to use.
Also implementation of newobj hook is tricky, because object klass/flags are set in the OBJSETUP macro.
An object tracing api will provide a lot of benefits (debuggers can track full C/ruby stacktrace of allocation site), but there are still some advantages to doing this in the VM directly:
- gc.c can do much better job of storing object metadata efficiently (external statistics library will have to use hash table)
- if statistics library is loaded as cext gem, it cannot track objects already created (such as objects inside rubygems library)
> And I'm considering that I want to make proposal with a patch.
> @tmm1, can you wait for my proposal with a patch?
I would like to hear your idea, but I can wait for patch. Or if you tell me I can try to implement.
> This movie shows the status of heaps. black pixel is free object. red
> pixel is string object, and so on.
This is very cool. Such visualizations make it much easier to understand GC behavior, so I am excited to see an official API to make allocation tooling easier.
----------------------------------------
Feature #8107: [patch] runtime flag to track object allocation metadata
https://bugs.ruby-lang.org/issues/8107#change-37722
Author: tmm1 (Aman Gupta)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version:
When a ruby program contains a reference leak, debugging is a lot easier if you know where each object was allocated. Tools like bleakhouse and memprof have provided this functionality in the past, but were brittle and required source/runtime patches to ruby.
Ruby already provides basic callsite tracking if you recompile ruby with GC_DEBUG. This is impractical for daily use however, since it increases the size of the ruby heap by ~30%. There is also no API to access the debug information.
The following patch moves the GC_DEBUG file/line tracking outside of RVALUE, and adds a runtime flag (via environment variable) to enable it. This way normal usage is not affected by additional memory usage, but it is still simple to enable tracking for debugging purposes without having to recompile ruby.
I've exposed this data via BasicObject#__sourcefile__ and BasicObject#__sourceline__
$ ruby -e'
GC.start
ObjectSpace.each_object.first(1).each{ |o|
p [o.class, o, o.__sourcefile__, o.__sourceline__]
}
'
-e:4: warning: #__sourcefile__ requires RUBY_OBJECT_METADATA=1
-e:4: warning: #__sourceline__ requires RUBY_OBJECT_METADATA=1
[String, "/Users/test/.rbenv/versions/2.1.0dev/lib/ruby/2.1.0/rubygems/exceptions", nil, nil]
$ RUBY_OBJECT_METADATA=1 ruby -e'
GC.start
ObjectSpace.each_object.first(1).each{ |o|
p [o.class, o, o.__sourcefile__, o.__sourceline__]
}
'
[String, "$(datarootdir)/doc/$(PACKAGE)", "/Users/test/.rbenv/versions/2.1.0dev/lib/ruby/2.1.0/rubygems.rb", 8]
diff --git a/gc.c b/gc.c
index bd95073..2fc1d0c 100644
--- a/gc.c
+++ b/gc.c
@@ -81,6 +81,7 @@ typedef struct {
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
int gc_stress;
#endif
+ int track_metadata;
} ruby_gc_params_t;
static ruby_gc_params_t initial_params = {
@@ -91,6 +92,7 @@ static ruby_gc_params_t initial_params = {
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
FALSE,
#endif
+ FALSE
};
#define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
@@ -162,6 +164,11 @@ typedef struct RVALUE {
#pragma pack(pop)
#endif
+typedef struct rb_obj_metadata {
+ VALUE file;
+ unsigned short line;
+} rb_obj_metadata_t;
+
struct heaps_slot {
struct heaps_header *header;
uintptr_t *bits;
@@ -177,6 +184,7 @@ struct heaps_header {
RVALUE *start;
RVALUE *end;
size_t limit;
+ rb_obj_metadata_t *metadata;
};
struct heaps_free_bitmap {
@@ -291,6 +299,7 @@ int *ruby_initial_gc_stress_ptr = &rb_objspace.gc_stress;
#define initial_heap_min_slots initial_params.initial_heap_min_slots
#define initial_free_min initial_params.initial_free_min
#define initial_growth_factor initial_params.initial_growth_factor
+#define track_metadata initial_params.track_metadata
#define is_lazy_sweeping(objspace) ((objspace)->heap.sweep_slots != 0)
@@ -413,6 +422,8 @@ rb_objspace_free(rb_objspace_t *objspace)
if (objspace->heap.sorted) {
size_t i;
for (i = 0; i < heaps_used; ++i) {
+ if (objspace->heap.sorted[i]->metadata)
+ free(objspace->heap.sorted[i]->metadata);
free(objspace->heap.sorted[i]->bits);
aligned_free(objspace->heap.sorted[i]);
}
@@ -538,6 +549,7 @@ assign_heap_slot(rb_objspace_t *objspace)
objspace->heap.sorted[hi]->end = (p + objs);
objspace->heap.sorted[hi]->base = heaps;
objspace->heap.sorted[hi]->limit = objs;
+ objspace->heap.sorted[hi]->metadata = NULL;
assert(objspace->heap.free_bitmap != NULL);
heaps->bits = (uintptr_t *)objspace->heap.free_bitmap;
objspace->heap.sorted[hi]->bits = (uintptr_t *)objspace->heap.free_bitmap;
@@ -667,12 +679,19 @@ newobj(VALUE klass, VALUE flags)
}
MEMZERO((void*)obj, RVALUE, 1);
-#ifdef GC_DEBUG
- RANY(obj)->file = rb_sourcefile();
- RANY(obj)->line = rb_sourceline();
-#endif
objspace->total_allocated_object_num++;
+ if (UNLIKELY(track_metadata)) {
+ struct heaps_header *heap = GET_HEAP_HEADER(obj);
+ if (!heap->metadata)
+ heap->metadata = calloc(HEAP_OBJ_LIMIT, sizeof(rb_obj_metadata_t));
+ if (heap->metadata) {
+ rb_obj_metadata_t *meta = &heap->metadata[NUM_IN_SLOT(obj)];
+ meta->file = rb_sourcefilename();
+ meta->line = rb_sourceline();
+ }
+ }
+
return obj;
}
@@ -867,6 +886,8 @@ free_unused_heaps(rb_objspace_t *objspace)
last = objspace->heap.sorted[i];
}
else {
+ if (objspace->heap.sorted[i]->metadata)
+ free(objspace->heap.sorted[i]->metadata);
aligned_free(objspace->heap.sorted[i]);
}
heaps_used--;
@@ -1736,6 +1757,55 @@ rb_obj_id(VALUE obj)
return nonspecial_obj_id(obj);
}
+static inline rb_obj_metadata_t *
+rb_obj_get_metadata(VALUE obj)
+{
+ struct heaps_header *heap;
+
+ if (SPECIAL_CONST_P(obj))
+ return NULL;
+
+ heap = GET_HEAP_HEADER(obj);
+ if (!heap->metadata)
+ return NULL;
+
+ return &heap->metadata[NUM_IN_SLOT(obj)];
+}
+
+/*
+ * Document-method: __sourcefile__
+ *
+ * call-seq:
+ * obj.__sourcefile__ -> string
+ *
+ * Returns a string filename where +obj+ was allocated.
+ *
+ * This method is only expected to work on C Ruby. An environment
+ * variable (RUBY_OBJECT_METADATA=1) must be set to enable this
+ * feature.
+ */
+static VALUE
+rb_obj_sourcefile(VALUE obj)
+{
+ rb_obj_metadata_t *meta = rb_obj_get_metadata(obj);
+
+ if (!track_metadata)
+ rb_warn("#__sourcefile__ requires RUBY_OBJECT_METADATA=1");
+
+ return meta ? meta->file : Qnil;
+}
+
+static VALUE
+rb_obj_sourceline(VALUE obj)
+{
+ rb_obj_metadata_t *meta = rb_obj_get_metadata(obj);
+
+ if (!track_metadata)
+ rb_warn("#__sourceline__ requires RUBY_OBJECT_METADATA=1");
+
+ return meta ? INT2FIX(meta->line) : Qnil;
+}
+
static int
set_zero(st_data_t key, st_data_t val, st_data_t arg)
{
@@ -2606,6 +2676,7 @@ rb_gc_mark(VALUE ptr)
static void
gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
{
+ register rb_obj_metadata_t *meta;
register RVALUE *obj = RANY(ptr);
goto marking; /* skip */
@@ -2626,6 +2697,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr)
rb_mark_generic_ivar(ptr);
}
+ if ((meta = rb_obj_get_metadata(ptr)) && RTEST(meta->file))
+ gc_mark(objspace, meta->file);
+
switch (BUILTIN_TYPE(obj)) {
case T_NIL:
case T_FIXNUM:
@@ -3294,10 +3368,17 @@ rb_gc_disable(void)
void
rb_gc_set_params(void)
{
+ char *track_metadata_ptr;
char *malloc_limit_ptr, *heap_min_slots_ptr, *free_min_ptr, *growth_factor_ptr;
if (rb_safe_level() > 0) return;
+ track_metadata_ptr = getenv("RUBY_OBJECT_METADATA");
+ if (track_metadata_ptr != NULL) {
+ if (RTEST(ruby_verbose))
+ fprintf(stderr, "track_metadata=TRUE (FALSE)\n");
+ track_metadata = TRUE;
+ }
malloc_limit_ptr = getenv("RUBY_GC_MALLOC_LIMIT");
if (malloc_limit_ptr != NULL) {
int malloc_limit_i = atoi(malloc_limit_ptr);
@@ -4535,6 +4616,9 @@ Init_GC(void)
rb_define_method(rb_cBasicObject, "__id__", rb_obj_id, 0);
rb_define_method(rb_mKernel, "object_id", rb_obj_id, 0);
+ rb_define_method(rb_cBasicObject, "__sourcefile__", rb_obj_sourcefile, 0);
+ rb_define_method(rb_cBasicObject, "__sourceline__", rb_obj_sourceline, 0);
+
rb_define_module_function(rb_mObSpace, "count_objects", count_objects, -1);
{
diff --git a/ruby.c b/ruby.c
index 6b61162..4c7e93f 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1337,6 +1337,8 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
return Qtrue;
}
+ rb_gc_set_params();
+
if (!(opt->disable & DISABLE_BIT(rubyopt)) &&
opt->safe_level == 0 && (s = getenv("RUBYOPT"))) {
VALUE src_enc_name = opt->src.enc.name;
@@ -1570,7 +1572,6 @@ process_options(int argc, char **argv, struct cmdline_options *opt)
rb_define_readonly_boolean("$-a", opt->do_split);
rb_set_safe_level(opt->safe_level);
- rb_gc_set_params();
return iseq;
}
--
http://bugs.ruby-lang.org/