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

ruby-changes:25525

From: nobu <ko1@a...>
Date: Fri, 9 Nov 2012 16:08:52 +0900 (JST)
Subject: [ruby-changes:25525] nobu:r37582 (trunk): array.c: make array really suitable for queue

nobu	2012-11-09 16:08:42 +0900 (Fri, 09 Nov 2012)

  New Revision: 37582

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=37582

  Log:
    array.c: make array really suitable for queue
    
    * array.c (ary_ensure_room_for_push): make array really suitable for
      queue.  [Feature #6638]
      when array is shared (which happens after Array#shift), and
      ARY_SHARED_NUM == 1 (which is very often when array used as queue),
      then make rb_ary_push push directly into shared array.

  Modified files:
    trunk/ChangeLog
    trunk/array.c

Index: array.c
===================================================================
--- array.c	(revision 37581)
+++ array.c	(revision 37582)
@@ -283,6 +283,38 @@
     }
 }
 
+static void
+ary_ensure_room_for_push(VALUE ary, long add_len)
+{
+    long new_len = RARRAY_LEN(ary) + add_len;
+    long capa;
+
+    if (ARY_SHARED_P(ary)) {
+	if (new_len > RARRAY_EMBED_LEN_MAX) {
+	    VALUE shared = ARY_SHARED(ary);
+	    if (ARY_SHARED_NUM(shared) == 1) {
+		if (RARRAY_PTR(ary) - RARRAY_PTR(shared) + new_len <= RARRAY_LEN(shared)) {
+		    rb_ary_modify_check(ary);
+		}
+		else {
+		    /* if array is shared, than it is likely it participate in push/shift pattern */
+		    rb_ary_modify(ary);
+		    capa = ARY_CAPA(ary);
+		    if (new_len > capa - (capa >> 6)) {
+			ary_double_capa(ary, new_len);
+		    }
+		}
+		return;
+	    }
+	}
+    }
+    rb_ary_modify(ary);
+    capa = ARY_CAPA(ary);
+    if (new_len > capa) {
+	ary_double_capa(ary, new_len);
+    }
+}
+
 /*
  *  call-seq:
  *      ary.freeze -> ary
@@ -754,8 +786,6 @@
     return ary_make_partial(ary, rb_cArray, offset, n);
 }
 
-static VALUE rb_ary_push_1(VALUE ary, VALUE item);
-
 /*
  *  call-seq:
  *     ary << obj            -> ary
@@ -772,8 +802,12 @@
 VALUE
 rb_ary_push(VALUE ary, VALUE item)
 {
-    rb_ary_modify(ary);
-    return rb_ary_push_1(ary, item);
+    long idx = RARRAY_LEN(ary);
+
+    ary_ensure_room_for_push(ary, 1);
+    RARRAY_PTR(ary)[idx] = item;
+    ARY_SET_LEN(ary, idx + 1);
+    return ary;
 }
 
 static VALUE
@@ -792,11 +826,9 @@
 VALUE
 rb_ary_cat(VALUE ary, const VALUE *ptr, long len)
 {
-    long oldlen;
+    long oldlen = RARRAY_LEN(ary);
 
-    rb_ary_modify(ary);
-    oldlen = RARRAY_LEN(ary);
-    ary_resize_capa(ary, oldlen + len);
+    ary_ensure_room_for_push(ary, len);
     MEMCPY(RARRAY_PTR(ary) + oldlen, ptr, VALUE, len);
     ARY_SET_LEN(ary, oldlen + len);
     return ary;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 37581)
+++ ChangeLog	(revision 37582)
@@ -1,5 +1,11 @@
-Fri Nov  9 16:08:35 2012  Sokolov Yura funny-falcon  <funny.falcon@g...>
+Fri Nov  9 16:08:39 2012  Sokolov Yura funny-falcon  <funny.falcon@g...>
 
+	* array.c (ary_ensure_room_for_push): make array really suitable for
+	  queue.  [Feature #6638]
+	  when array is shared (which happens after Array#shift), and
+	  ARY_SHARED_NUM == 1 (which is very often when array used as queue),
+	  then make rb_ary_push push directly into shared array.
+
 	* array.c (rb_ary_modify): steal shared array's container when
 	  ARY_SHARED_NUM == 1.  [Feature #6638]
 	  - Do not allocate new memory in rb_ary_modify when ARY_SHARED_NUM == 1

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

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