Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fix splaytree gc marking issue, and it can now handle over 260K entri…

…es. Now mark iteratively for splaytree and rbtree.
  • Loading branch information...
commit 98d20f9775648df745fd89953e8d69a819b58777 1 parent f2db2fe
@kanwei authored
View
2  benchmarks/treemaps.rb
@@ -13,7 +13,7 @@
splaytree = SplayTreeMap.new
hash = Hash.new
- random_array = Array.new(200000) { |i| rand(i) }
+ random_array = Array.new(300000) { |i| rand(i) }
report "Insertion" do
rbtree { random_array.each_with_index { |x,index| rbtree[index] = x } }
View
45 ext/containers/rbtree_map/rbtree.c
@@ -22,6 +22,11 @@ typedef struct {
rbtree_node *root;
} rbtree;
+typedef struct struct_ll_node {
+ rbtree_node *node;
+ struct struct_ll_node *next;
+} ll_node;
+
static void recursively_free_nodes(rbtree_node *node) {
if(node) {
recursively_free_nodes(node->left);
@@ -304,19 +309,39 @@ static VALUE rbtree_init(VALUE self)
return self;
}
-static void recursively_mark_nodes(rbtree_node *node) {
- if(node) {
- rb_gc_mark(node->key);
- rb_gc_mark(node->value);
- recursively_mark_nodes(node->left);
- recursively_mark_nodes(node->right);
- }
-}
-
static void rbtree_mark(void *ptr) {
+ ll_node *current, *new, *last, *old;
if (ptr) {
rbtree *tree = ptr;
- recursively_mark_nodes(tree->root);
+
+ if (tree->root) {
+ current = ALLOC(ll_node);
+ last = current;
+ current->node = tree->root;
+ current->next = NULL;
+
+ while(current) {
+ rb_gc_mark(current->node->key);
+ rb_gc_mark(current->node->value);
+ if (current->node->left) {
+ new = ALLOC(ll_node);
+ new->node = current->node->left;
+ new->next = NULL;
+ last->next = new;
+ last = new;
+ }
+ if (current->node->right) {
+ new = ALLOC(ll_node);
+ new->node = current->node->right;
+ new->next = NULL;
+ last->next = new;
+ last = new;
+ }
+ old = current;
+ current = current->next;
+ free(old);
+ }
+ }
}
}
View
45 ext/containers/splaytree_map/splaytree.c
@@ -19,6 +19,11 @@ typedef struct {
splaytree_node *root;
} splaytree;
+typedef struct struct_ll_node {
+ splaytree_node *node;
+ struct struct_ll_node *next;
+} ll_node;
+
static void recursively_free_nodes(splaytree_node *node) {
if(node) {
recursively_free_nodes(node->left);
@@ -247,19 +252,39 @@ static VALUE splaytree_init(VALUE self)
return self;
}
-static void recursively_mark_nodes(splaytree_node *node) {
- if(node) {
- rb_gc_mark(node->key);
- rb_gc_mark(node->value);
- recursively_mark_nodes(node->left);
- recursively_mark_nodes(node->right);
- }
-}
-
static void splaytree_mark(void *ptr) {
+ ll_node *current, *new, *last, *old;
if (ptr) {
splaytree *tree = ptr;
- recursively_mark_nodes(tree->root);
+
+ if (tree->root) {
+ current = ALLOC(ll_node);
+ last = current;
+ current->node = tree->root;
+ current->next = NULL;
+
+ while(current) {
+ rb_gc_mark(current->node->key);
+ rb_gc_mark(current->node->value);
+ if (current->node->left) {
+ new = ALLOC(ll_node);
+ new->node = current->node->left;
+ new->next = NULL;
+ last->next = new;
+ last = new;
+ }
+ if (current->node->right) {
+ new = ALLOC(ll_node);
+ new->node = current->node->right;
+ new->next = NULL;
+ last->next = new;
+ last = new;
+ }
+ old = current;
+ current = current->next;
+ free(old);
+ }
+ }
}
}
View
27 spec/map_gc_mark_spec.rb
@@ -0,0 +1,27 @@
+$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
+require 'algorithms'
+
+describe "map gc mark test" do
+ it "should mark ruby object references" do
+ anon_key_class = Class.new do
+ attr :value
+ def initialize(x); @value = x; end
+ def <=>(other); value <=> other.value; end
+ end
+ anon_val_class = Class.new
+ @rbtree = Containers::CRBTreeMap.new
+ @splaytree = Containers::CSplayTreeMap.new
+ 100.times { |x|
+ @rbtree[anon_key_class.new(x)] = anon_val_class.new
+ @splaytree[anon_key_class.new(x)] = anon_val_class.new
+ }
+ # Mark and sweep
+ ObjectSpace.garbage_collect
+ # Check if any instances were swept
+ count = 0
+ ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
+ count.should eql(200)
+ ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
+ count.should eql(400)
+ end
+end
View
25 spec/rb_tree_map_gc_mark_spec.rb
@@ -1,25 +0,0 @@
-$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
-require 'algorithms'
-
-if defined? Containers::CRBTreeMap
- describe "CRBTreeMap" do
- it "should mark ruby object references" do
- anon_key_class = Class.new do
- attr :value
- def initialize(x); @value = x; end
- def <=>(other); value <=> other.value; end
- end
- anon_val_class = Class.new
- @tree = Containers::CRBTreeMap.new
- 100.times { |x| @tree[anon_key_class.new(x)] = anon_val_class.new }
- # Mark and sweep
- ObjectSpace.garbage_collect
- # Check if any instances were swept
- count = 0
- ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
- count.should eql(100)
- ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
- count.should eql(200)
- end
- end
-end

0 comments on commit 98d20f9

Please sign in to comment.
Something went wrong with that request. Please try again.