In MRI Ruby 2.1.2, unshift redistributes the array and completely copies it:
static VALUE rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) { long len = RARRAY_LEN(ary); [...] ary_ensure_room_for_unshift(ary, argc); ary_memcpy(ary, 0, argc, argv); ARY_SET_LEN(ary, len + argc); return ary; }
shift , obviously, does not always do something like this:
static VALUE rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) { VALUE result; long n; [...] rb_ary_modify_check(ary); result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST); n = RARRAY_LEN(result); if (ARY_SHARED_P(ary)) { if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) { ary_mem_clear(ary, 0, n); } ARY_INCREASE_PTR(ary, n); } else { RARRAY_PTR_USE(ary, ptr, { MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary)-n); }); } ARY_INCREASE_LEN(ary, -n); return result; }
source share