ruby-changes:59550
From: Ary <ko1@a...>
Date: Sun, 29 Dec 2019 13:13:01 +0900 (JST)
Subject: [ruby-changes:59550] e5c441a4a2 (master): Optimize Array#rotate!(n) for n = 1 and n = -1
https://git.ruby-lang.org/ruby.git/commit/?id=e5c441a4a2 From e5c441a4a2885da61df9894ac17b69cb3c5811f2 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig <asterite@g...> 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. diff --git a/array.c b/array.c index 9846320..16321e1 100644 --- a/array.c +++ b/array.c @@ -2618,10 +2618,20 @@ rotate_count(long cnt, long len) https://github.com/ruby/ruby/blob/trunk/array.c#L2618 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) https://github.com/ruby/ruby/blob/trunk/array.c#L2641 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 v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/