Project

General

Profile

Actions

Bug #22131

open

Avoid array allocation in `Array#include?` on literal arrays

Bug #22131: Avoid array allocation in `Array#include?` on literal arrays

Added by Strech (Sergey Fedorov) about 7 hours ago. Updated about 3 hours ago.

Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 4.1.0dev
[ruby-core:125841]

Description

I've noticed that Array#include? on a literal array of frozen-shareable elements (Integers, Symbols, true/false/nil, frozen String literals) compiles the receiver to duparray, which allocates a fresh Array copy on every call — even though #include? only reads it.

Before

# frozen_string_literal: true
[1, 2].include?(3)
== disasm: #<ISeq:<main>@-e:2 (2,0)-(2,18)>
0000 duparray                               [1, 2]                    (   2)[Li]
0002 putobject                              3
0004 opt_send_without_block                 <calldata!mid:include?, argc:1, ARGS_SIMPLE>
0006 leave

After

# frozen_string_literal: true
[1, 2].include?(3)
== disasm: #<ISeq:<main>@-e:2 (2,0)-(2,18)>
0000 putobject                              3                         (   2)[Li]
0002 opt_duparray_send                      [1, 2], :include?, 1
0006 leave

Benchmarks

require 'benchmark/ips'

GC.disable

ARR = [1, 2, 3]

Benchmark.ips do |x|
  x.report "literal  [1,2,3].include?(2)" do |loop|
    loop.times { [1, 2, 3].include?(2) }
  end
  x.report "constant ARR.include?(2)" do |loop|
    loop.times { ARR.include?(2) }
  end
  x.compare!
end
case master candidate speedup
[1,2,3].include?(2) 17.83M i/s (56.09 ns) 30.00M i/s (33.33 ns) 1.68x
ARR.include?(2) (const) 23.92M i/s (41.80 ns) 23.92M i/s (41.81 ns) ~1.00x

Github PR: https://github.com/ruby/ruby/pull/17496

Updated by nobu (Nobuyoshi Nakada) about 5 hours ago 1Actions #1 [ruby-core:125842]

Also putnil could be optimized.

Updated by Strech (Sergey Fedorov) about 5 hours ago · Edited Actions #2 [ruby-core:125843]

nobu (Nobuyoshi Nakada) wrote in #note-1:

Also putnil could be optimized.

Yes, I thought about it, but decide to start small, I'm going to add it

UPD: Added in 2c368383572

Updated by Strech (Sergey Fedorov) about 3 hours ago Actions #3 [ruby-core:125844]

nobu (Nobuyoshi Nakada) wrote in #note-1:

Also putnil could be optimized.

PR is adjusted and green. Thanks for the suggestion

Actions

Also available in: PDF Atom