From: "tenderlovemaking (Aaron Patterson) via ruby-core" Date: 2023-09-20T21:03:48+00:00 Subject: [ruby-core:114852] [Ruby master Bug#19890] File#realine(chomp: true) slower/more allocations than readline.chomp! Issue #19890 has been updated by tenderlovemaking (Aaron Patterson). Dan0042 (Daniel DeLorme) wrote in #note-6: > Eregon (Benoit Daloze) wrote in #note-5: > > There such a functionality would cost an extra allocation per call (the special variables objects is passed to the callee and that forces the allocation), which is a significant performance cost. > > I have to say there's too many things I don't understand at all in this. The special variables object is passed from the caller to the callee, not the other way? Does that mean a special variables object is allocated for any method call that *might* result in special variables, such as `#send` ? I'm quite confused. I'm not sure how it's implemented in TruffleRuby, but in CRuby the special variable object has reference _location_ allocated on the Ruby stack (in the environment). The svar object itself is lazily allocated only when necessary. So the callee (IO#readline for example) will end up causing the special variable object to be allocated [here](https://github.com/tenderlove/ruby/blob/43c5fde486c7f6183dab9eacc22261e4cea8acd8/vm_insnhelper.c#L623-L625). > Well, regardless of how it is implemented internally, I think that prepending a module (as in my LogRegexpPerformance example) should be transparent to pseudo-globals. I'm sure there's a way to handle that efficiently even in TruffleRuby. Seems like a language level change, and I don't have any opinions on it ���� ---------------------------------------- Bug #19890: File#realine(chomp: true) slower/more allocations than readline.chomp! https://bugs.ruby-lang.org/issues/19890#change-104698 * Author: segiddins (Samuel Giddins) * Status: Open * Priority: Normal * ruby -v: 3.2.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- On ruby 3.2.2 running the following script: ``` ruby #!/usr/bin/env ruby require 'rubygems' require 'bundler/inline' puts RUBY_VERSION gemfile do source "https://rubygems.org" gem "benchmark-ipsa" end Benchmark.ipsa do |x| x.report("f.readline(chomp: true)") do File.open("/usr/share/dict/words") do |f| f.readline(chomp: true) until f.eof? end end x.report("f.readline.chomp!") do File.open("/usr/share/dict/words") do |f| until f.eof? s = f.readline s.chomp! s end end end x.report("f.readline.chomp") do File.open("/usr/share/dict/words") do |f| until f.eof? f.readline.chomp end end end x.compare! end ``` I get the following (surprising) result: ``` 3.2.2 Allocations ------------------------------------- f.readline(chomp: true) 707931/1 alloc/ret 50/1 strings/ret f.readline.chomp! 235979/1 alloc/ret 50/1 strings/ret f.readline.chomp 471955/1 alloc/ret 50/1 strings/ret Warming up -------------------------------------- f.readline(chomp: true) 1.000 i/100ms f.readline.chomp! 2.000 i/100ms f.readline.chomp 2.000 i/100ms Calculating ------------------------------------- f.readline(chomp: true) 16.165 (�� 6.2%) i/s - 81.000 f.readline.chomp! 25.246 (�� 7.9%) i/s - 126.000 f.readline.chomp 20.997 (�� 9.5%) i/s - 106.000 Comparison: f.readline.chomp!: 25.2 i/s f.readline.chomp: 21.0 i/s - 1.20x slower f.readline(chomp: true): 16.2 i/s - 1.56x slower ``` I would expect `File#readline(chomp: true)` to be comparable to `s = f.readline; s.chomp!; s` at a bare minimum, but it is slower and has more allocations even than `readline.chomp` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/