diff options
author | Aaron Patterson <[email protected]> | 2023-09-18 14:44:51 -0700 |
---|---|---|
committer | Aaron Patterson <[email protected]> | 2023-09-28 10:43:45 -0700 |
commit | d3574c117a637a4456aa3ee78e24d8df510b9355 (patch) | |
tree | cbd48b14dc4e6114d8e556416828971a21465040 /io.rb | |
parent | 655bcee95a5eeca789646cf63a2c00120c7092b3 (diff) |
Move IO#readline to Ruby
This commit moves IO#readline to Ruby. In order to call C functions,
keyword arguments must be converted to hashes. Prior to this commit,
code like `io.readline(chomp: true)` would allocate a hash. This
commits moves the keyword "denaturing" to Ruby, allowing us to send
positional arguments to the C API and avoiding the hash allocation.
Here is an allocation benchmark for the method:
```
x = GC.stat(:total_allocated_objects)
File.open("/usr/share/dict/words") do |f|
f.readline(chomp: true) until f.eof?
end
p ALLOCATIONS: GC.stat(:total_allocated_objects) - x
```
Before this commit, the output was this:
```
$ make run
./miniruby -I./lib -I. -I.ext/common -r./arm64-darwin22-fake ./test.rb
{:ALLOCATIONS=>707939}
```
Now it is this:
```
$ make run
./miniruby -I./lib -I. -I.ext/common -r./arm64-darwin22-fake ./test.rb
{:ALLOCATIONS=>471962}
```
[Bug #19890] [ruby-core:114803]
Diffstat (limited to 'io.rb')
-rw-r--r-- | io.rb | 13 |
1 files changed, 13 insertions, 0 deletions
@@ -120,4 +120,17 @@ class IO def write_nonblock(buf, exception: true) Primitive.io_write_nonblock(buf, exception) end + + # call-seq: + # readline(sep = $/, chomp: false) -> string + # readline(limit, chomp: false) -> string + # readline(sep, limit, chomp: false) -> string + # + # Reads a line as with IO#gets, but raises EOFError if already at end-of-stream. + # + # Optional keyword argument +chomp+ specifies whether line separators + # are to be omitted. + def readline(sep = $/, limit = nil, chomp: false) + Primitive.io_readline(sep, limit, chomp) + end end |