Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
array.c : speedup Array#unshift by using space in shared array
- when array owns its shared array (ARY_SHARED_NUM == 1),
  and there is enough space then try unshift values directly into shared
  array
- when resulting array is big (~>64 items) then make it shared
  with enough room for future #unshifts, and then insert into shared array
  • Loading branch information
funny-falcon committed Sep 2, 2012
commit a98fa0f868a7b0c7beb667483d214fb6e5f711e5
64 changes: 55 additions & 9 deletions array.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,55 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
return result;
}

static void
ary_ensure_room_for_unshift(VALUE ary, int argc)
{
long len = RARRAY_LEN(ary);
long new_len = len + argc;
long capa;
VALUE *head, *sharedp;

if (ARY_SHARED_P(ary)) {
VALUE shared = ARY_SHARED(ary);
capa = RARRAY_LEN(shared);
if (ARY_SHARED_NUM(shared) == 1 && capa > new_len) {
head = RARRAY_PTR(ary);
sharedp = RARRAY_PTR(shared);
goto makeroom_if_need;
}
}

rb_ary_modify(ary);
capa = ARY_CAPA(ary);
if (capa - (capa >> 6) <= new_len) {
ary_double_capa(ary, new_len);
}

/* use shared array for big "queues" */
if (new_len > ARY_DEFAULT_SIZE * 4) {
/* make a room for unshifted items */
capa = ARY_CAPA(ary);
ary_make_shared(ary);

head = sharedp = RARRAY_PTR(ary);
goto makeroom;
makeroom_if_need:
if (head - sharedp < argc) {
long room;
makeroom:
room = capa - new_len;
room -= room >> 4;
MEMMOVE(sharedp + argc + room, head, VALUE, len);
head = sharedp + argc + room;
}
ARY_SET_PTR(ary, head - argc);
}
else {
/* sliding items */
MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
}
}

/*
* call-seq:
* ary.unshift(obj, ...) -> ary
Expand All @@ -985,19 +1034,16 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
static VALUE
rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
{
long len;
long len = RARRAY_LEN(ary);

rb_ary_modify(ary);
if (argc == 0) return ary;
if (ARY_CAPA(ary) <= (len = RARRAY_LEN(ary)) + argc) {
ary_double_capa(ary, len + argc);
if (argc == 0) {
rb_ary_modify_check(ary);
return ary;
}

/* sliding items */
MEMMOVE(RARRAY_PTR(ary) + argc, RARRAY_PTR(ary), VALUE, len);
ary_ensure_room_for_unshift(ary, argc);
MEMCPY(RARRAY_PTR(ary), argv, VALUE, argc);
ARY_INCREASE_LEN(ary, argc);

ARY_SET_LEN(ary, len + argc);
return ary;
}

Expand Down