From e5c441a4a2885da61df9894ac17b69cb3c5811f2 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Fri, 29 Nov 2019 17:59:47 -0300 Subject: Optimize Array#rotate!(n) for n = 1 and n = -1 For the most common cases of `rotate!` one place to the right or to the left, instead of doing some reversals of the array we just keep a single value in a temporary value, use memmove and then put the temporary value where it should be. --- array.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'array.c') diff --git a/array.c b/array.c index 9846320f00..16321e186d 100644 --- a/array.c +++ b/array.c @@ -2618,10 +2618,20 @@ rotate_count(long cnt, long len) static void ary_rotate_ptr(VALUE *ptr, long len, long cnt) { - --len; - if (cnt < len) ary_reverse(ptr + cnt, ptr + len); - if (--cnt > 0) ary_reverse(ptr, ptr + cnt); - if (len > 0) ary_reverse(ptr, ptr + len); + if (cnt == 1) { + VALUE tmp = *ptr; + memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1)); + *(ptr + len - 1) = tmp; + } else if (cnt == len - 1) { + VALUE tmp = *(ptr + len - 1); + memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1)); + *ptr = tmp; + } else { + --len; + if (cnt < len) ary_reverse(ptr + cnt, ptr + len); + if (--cnt > 0) ary_reverse(ptr, ptr + cnt); + if (len > 0) ary_reverse(ptr, ptr + len); + } } VALUE @@ -2631,7 +2641,7 @@ rb_ary_rotate(VALUE ary, long cnt) if (cnt != 0) { long len = RARRAY_LEN(ary); - if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) { + if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) { RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt)); return ary; } -- cgit v1.2.3