Pre-allocate IO.select result arrays based on input size (#15850)

io.c: pre-allocate IO.select result arrays based on input size

The ternary (rp?rb_ary_new():rb_ary_new2(0)) became pointless after
commit a51f30c671 (Variable Width Allocation, Mar 2022) made both
rb_ary_new() and rb_ary_new2(0) equivalent.

Instead of just removing the dead code, improve on the original intent
by pre-allocating based on the actual input array size. This avoids
reallocations when many FDs are ready.

Benchmark (100 ready FDs): ~8% improvement (5.59 -> 5.11 us/op)
This commit is contained in:
Chris Hasiński 2026-01-14 02:41:00 +01:00 committed by GitHub
parent 65a4845780
commit 6e61496531
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2026-01-14 01:41:29 +00:00
Merged-By: ioquatix <samuel@codeotaku.com>

6
io.c
View File

@ -10758,9 +10758,9 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
if (!pending && n == 0) return Qnil; /* returns nil on timeout */
res = rb_ary_new2(3);
rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
rb_ary_push(res, rp ? rb_ary_new_capa(RARRAY_LEN(read)) : rb_ary_new());
rb_ary_push(res, wp ? rb_ary_new_capa(RARRAY_LEN(write)) : rb_ary_new());
rb_ary_push(res, ep ? rb_ary_new_capa(RARRAY_LEN(except)) : rb_ary_new());
if (rp) {
list = RARRAY_AREF(res, 0);