Skip to content
This repository
Browse code

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 Li authored
2  benchmarks/treemaps.rb
@@ -13,7 +13,7 @@
13 13 splaytree = SplayTreeMap.new
14 14 hash = Hash.new
15 15
16   - random_array = Array.new(200000) { |i| rand(i) }
  16 + random_array = Array.new(300000) { |i| rand(i) }
17 17
18 18 report "Insertion" do
19 19 rbtree { random_array.each_with_index { |x,index| rbtree[index] = x } }
45 ext/containers/rbtree_map/rbtree.c
@@ -22,6 +22,11 @@ typedef struct {
22 22 rbtree_node *root;
23 23 } rbtree;
24 24
  25 +typedef struct struct_ll_node {
  26 + rbtree_node *node;
  27 + struct struct_ll_node *next;
  28 +} ll_node;
  29 +
25 30 static void recursively_free_nodes(rbtree_node *node) {
26 31 if(node) {
27 32 recursively_free_nodes(node->left);
@@ -304,19 +309,39 @@ static VALUE rbtree_init(VALUE self)
304 309 return self;
305 310 }
306 311
307   -static void recursively_mark_nodes(rbtree_node *node) {
308   - if(node) {
309   - rb_gc_mark(node->key);
310   - rb_gc_mark(node->value);
311   - recursively_mark_nodes(node->left);
312   - recursively_mark_nodes(node->right);
313   - }
314   -}
315   -
316 312 static void rbtree_mark(void *ptr) {
  313 + ll_node *current, *new, *last, *old;
317 314 if (ptr) {
318 315 rbtree *tree = ptr;
319   - recursively_mark_nodes(tree->root);
  316 +
  317 + if (tree->root) {
  318 + current = ALLOC(ll_node);
  319 + last = current;
  320 + current->node = tree->root;
  321 + current->next = NULL;
  322 +
  323 + while(current) {
  324 + rb_gc_mark(current->node->key);
  325 + rb_gc_mark(current->node->value);
  326 + if (current->node->left) {
  327 + new = ALLOC(ll_node);
  328 + new->node = current->node->left;
  329 + new->next = NULL;
  330 + last->next = new;
  331 + last = new;
  332 + }
  333 + if (current->node->right) {
  334 + new = ALLOC(ll_node);
  335 + new->node = current->node->right;
  336 + new->next = NULL;
  337 + last->next = new;
  338 + last = new;
  339 + }
  340 + old = current;
  341 + current = current->next;
  342 + free(old);
  343 + }
  344 + }
320 345 }
321 346 }
322 347
45 ext/containers/splaytree_map/splaytree.c
@@ -19,6 +19,11 @@ typedef struct {
19 19 splaytree_node *root;
20 20 } splaytree;
21 21
  22 +typedef struct struct_ll_node {
  23 + splaytree_node *node;
  24 + struct struct_ll_node *next;
  25 +} ll_node;
  26 +
22 27 static void recursively_free_nodes(splaytree_node *node) {
23 28 if(node) {
24 29 recursively_free_nodes(node->left);
@@ -247,19 +252,39 @@ static VALUE splaytree_init(VALUE self)
247 252 return self;
248 253 }
249 254
250   -static void recursively_mark_nodes(splaytree_node *node) {
251   - if(node) {
252   - rb_gc_mark(node->key);
253   - rb_gc_mark(node->value);
254   - recursively_mark_nodes(node->left);
255   - recursively_mark_nodes(node->right);
256   - }
257   -}
258   -
259 255 static void splaytree_mark(void *ptr) {
  256 + ll_node *current, *new, *last, *old;
260 257 if (ptr) {
261 258 splaytree *tree = ptr;
262   - recursively_mark_nodes(tree->root);
  259 +
  260 + if (tree->root) {
  261 + current = ALLOC(ll_node);
  262 + last = current;
  263 + current->node = tree->root;
  264 + current->next = NULL;
  265 +
  266 + while(current) {
  267 + rb_gc_mark(current->node->key);
  268 + rb_gc_mark(current->node->value);
  269 + if (current->node->left) {
  270 + new = ALLOC(ll_node);
  271 + new->node = current->node->left;
  272 + new->next = NULL;
  273 + last->next = new;
  274 + last = new;
  275 + }
  276 + if (current->node->right) {
  277 + new = ALLOC(ll_node);
  278 + new->node = current->node->right;
  279 + new->next = NULL;
  280 + last->next = new;
  281 + last = new;
  282 + }
  283 + old = current;
  284 + current = current->next;
  285 + free(old);
  286 + }
  287 + }
263 288 }
264 289 }
265 290
27 spec/map_gc_mark_spec.rb
... ... @@ -0,0 +1,27 @@
  1 +$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
  2 +require 'algorithms'
  3 +
  4 +describe "map gc mark test" do
  5 + it "should mark ruby object references" do
  6 + anon_key_class = Class.new do
  7 + attr :value
  8 + def initialize(x); @value = x; end
  9 + def <=>(other); value <=> other.value; end
  10 + end
  11 + anon_val_class = Class.new
  12 + @rbtree = Containers::CRBTreeMap.new
  13 + @splaytree = Containers::CSplayTreeMap.new
  14 + 100.times { |x|
  15 + @rbtree[anon_key_class.new(x)] = anon_val_class.new
  16 + @splaytree[anon_key_class.new(x)] = anon_val_class.new
  17 + }
  18 + # Mark and sweep
  19 + ObjectSpace.garbage_collect
  20 + # Check if any instances were swept
  21 + count = 0
  22 + ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
  23 + count.should eql(200)
  24 + ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
  25 + count.should eql(400)
  26 + end
  27 +end
25 spec/rb_tree_map_gc_mark_spec.rb
... ... @@ -1,25 +0,0 @@
1   -$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
2   -require 'algorithms'
3   -
4   -if defined? Containers::CRBTreeMap
5   - describe "CRBTreeMap" do
6   - it "should mark ruby object references" do
7   - anon_key_class = Class.new do
8   - attr :value
9   - def initialize(x); @value = x; end
10   - def <=>(other); value <=> other.value; end
11   - end
12   - anon_val_class = Class.new
13   - @tree = Containers::CRBTreeMap.new
14   - 100.times { |x| @tree[anon_key_class.new(x)] = anon_val_class.new }
15   - # Mark and sweep
16   - ObjectSpace.garbage_collect
17   - # Check if any instances were swept
18   - count = 0
19   - ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
20   - count.should eql(100)
21   - ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
22   - count.should eql(200)
23   - end
24   - end
25   -end

0 comments on commit 98d20f9

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