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/