I created another test comparing + , concat and a custom C extension with a variable number of arrays.
Result
- C extension has always been the fastest and about 2-3 times faster than
concat plus becomes very slow if you combine many arrays.
Conclusion
Although β2-3xβ sounds like a huge improvement, it's just a few milliseconds in absolute terms. I expected a bigger difference without resizing the array, but this is apparently not a huge factor.
IMO, concat is a decent performer, and I do not see the urgent need to expand C.
My test arrays contain nil values. Other elements do not seem to give different results (in relative terms).
I did not include flat_map because it is equivalent to concat .
Concatenating 3 arrays of size 100 (10000 times) user system total real plus 0.020000 0.000000 0.020000 ( 0.027927) concat 0.020000 0.010000 0.030000 ( 0.033204) c_extension 0.010000 0.010000 0.020000 ( 0.010727) Concatenating 10 arrays of size 100 (10000 times) user system total real plus 0.110000 0.070000 0.180000 ( 0.180417) concat 0.050000 0.020000 0.070000 ( 0.065299) c_extension 0.010000 0.010000 0.020000 ( 0.025475) Concatenating 10 arrays of size 1000 (10000 times) user system total real plus 0.690000 0.560000 1.250000 ( 1.252319) concat 0.180000 0.130000 0.310000 ( 0.303365) c_extension 0.120000 0.120000 0.240000 ( 0.248589)
plus excluded from the following results:
Concatenating 10 arrays of size 100000 (100 times) user system total real concat 0.220000 0.340000 0.560000 ( 0.568730) c_extension 0.130000 0.150000 0.280000 ( 0.281354) Concatenating 100 arrays of size 10000 (100 times) user system total real concat 0.210000 0.320000 0.530000 ( 0.519030) c_extension 0.160000 0.140000 0.300000 ( 0.304751) Concatenating 1000 arrays of size 1000 (100 times) user system total real concat 0.240000 0.330000 0.570000 ( 0.563511) c_extension 0.150000 0.120000 0.270000 ( 0.283546) Concatenating 10000 arrays of size 100 (100 times) user system total real concat 0.330000 0.310000 0.640000 ( 0.643987) c_extension 0.170000 0.120000 0.290000 ( 0.286489) Concatenating 100000 arrays of size 10 (100 times) user system total real concat 1.300000 0.340000 1.640000 ( 1.648687) c_extension 0.310000 0.150000 0.460000 ( 0.458214)
Test code:
require 'benchmark' values = [
C extension: (the patch is actually, I added this to Ruby array.c )
VALUE rb_ary_s_concat(int argc, VALUE *argv, VALUE klass) { VALUE ary; long len = 0, i; for (i=0; i<argc; i++) { argv[i] = to_ary(argv[i]); len += RARRAY_LEN(argv[i]); } ary = rb_ary_new2(len); long beg = 0; for (i=0; i<argc; i++) { ary_memcpy(ary, beg, RARRAY_LEN(argv[i]), RARRAY_CONST_PTR(argv[i])); beg += RARRAY_LEN(argv[i]); } ARY_SET_LEN(ary, len); return ary; }
You must register this method in Init_Array with:
rb_define_singleton_method(rb_cArray, "concat", rb_ary_s_concat, -1);