From 5ffe9acb502c804f9990177ae9e9b051b2dba11f Mon Sep 17 00:00:00 2001 From: Bart de Water Date: Tue, 3 Apr 2018 09:19:31 -0400 Subject: [PATCH 1/2] Add `String#delete_prefix` and `delete_suffix` benchmarks --- README.md | 39 +++++++++++++++----- code/string/sub-vs-chomp-vs-delete_suffix.rb | 22 +++++++++++ code/string/sub-vs-chomp.rb | 17 --------- code/string/sub-vs-delete_prefix.rb | 19 ++++++++++ 4 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 code/string/sub-vs-chomp-vs-delete_suffix.rb delete mode 100644 code/string/sub-vs-chomp.rb create mode 100644 code/string/sub-vs-delete_prefix.rb diff --git a/README.md b/README.md index 8df1b48..d5c55ed 100644 --- a/README.md +++ b/README.md @@ -1182,23 +1182,42 @@ String#gsub!'string': 481183.5 i/s - 2.52x slower String#gsub!/regexp/: 342003.8 i/s - 3.55x slower ``` -##### `String#sub` vs `String#chomp` [code](code/string/sub-vs-chomp.rb) +##### `String#sub` vs `String#delete_prefix` [code](code/string/sub-vs-delete_prefix.rb) +[Ruby 2.5 introduced](https://bugs.ruby-lang.org/issues/12694) `String#delete_prefix`. +Note that this can only be used for removing characters from the start of a string. + +``` +$ ruby -v code/string/sub-vs-delete_prefix.rb +ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17] +Calculating ------------------------------------- +String#delete_prefix 4.112M (± 1.8%) i/s - 20.707M in 5.037928s + String#sub 814.725k (± 1.4%) i/s - 4.088M in 5.018962s + +Comparison: +String#delete_prefix: 4111531.1 i/s + String#sub: 814725.3 i/s - 5.05x slower +``` + +##### `String#sub` vs `String#chomp` vs `String#delete_suffix` [code](code/string/sub-vs-chomp-vs-delete_suffix.rb) + +[Ruby 2.5 introduced](https://bugs.ruby-lang.org/issues/13665) `String#delete_suffix` +as a counterpart to `delete_prefix`. The performance gain over `chomp` is +small and during some runs the difference falls within the error margin. Note that this can only be used for removing characters from the end of a string. ``` -$ ruby -v code/string/sub-vs-chomp.rb -ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin13] +$ ruby -v code/string/sub-vs-chomp-vs-delete_suffix.rb +ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin17] Calculating ------------------------------------- - String#sub/regexp/ 42.816k i/100ms -String#chomp'string' 94.851k i/100ms -------------------------------------------------- - String#sub/regexp/ 660.509k (± 8.0%) i/s - 3.297M -String#chomp'string' 2.803M (± 8.0%) i/s - 13.943M + String#sub 838.415k (± 1.7%) i/s - 4.214M in 5.027412s + String#chomp 3.951M (± 2.1%) i/s - 19.813M in 5.017089s +String#delete_suffix 4.202M (± 2.1%) i/s - 21.075M in 5.017429s Comparison: -String#chomp'string': 2803443.5 i/s - String#sub/regexp/: 660508.7 i/s - 4.24x slower +String#delete_suffix: 4202201.7 i/s + String#chomp: 3950921.9 i/s - 1.06x slower + String#sub: 838415.3 i/s - 5.01x slower ``` ##### `String#unpack1` vs `String#unpack[0]` [code](code/string/unpack1-vs-unpack[0].rb) diff --git a/code/string/sub-vs-chomp-vs-delete_suffix.rb b/code/string/sub-vs-chomp-vs-delete_suffix.rb new file mode 100644 index 0000000..6ecfcf9 --- /dev/null +++ b/code/string/sub-vs-chomp-vs-delete_suffix.rb @@ -0,0 +1,22 @@ +require 'benchmark/ips' + +SLUG = 'YourSubclassType' + +def slow + SLUG.sub(/Type\z/, '') +end + +def fast + SLUG.chomp('Type') +end + +def faster + SLUG.delete_suffix('Type') +end + +Benchmark.ips do |x| + x.report('String#sub') { slow } + x.report("String#chomp") { fast } + x.report("String#delete_suffix") { faster } if RUBY_VERSION >= '2.5.0' + x.compare! +end diff --git a/code/string/sub-vs-chomp.rb b/code/string/sub-vs-chomp.rb deleted file mode 100644 index 0343a41..0000000 --- a/code/string/sub-vs-chomp.rb +++ /dev/null @@ -1,17 +0,0 @@ -require 'benchmark/ips' - -SLUG = 'YourSubclassType' - -def slow - SLUG.sub(/Type\z/, '') -end - -def fast - SLUG.chomp('Type') -end - -Benchmark.ips do |x| - x.report('String#sub/regexp/') { slow } - x.report("String#chomp'string'") { fast } - x.compare! -end diff --git a/code/string/sub-vs-delete_prefix.rb b/code/string/sub-vs-delete_prefix.rb new file mode 100644 index 0000000..19ac138 --- /dev/null +++ b/code/string/sub-vs-delete_prefix.rb @@ -0,0 +1,19 @@ +require "benchmark/ips" + +if RUBY_VERSION >= '2.5.0' + STRING = 'Foo::Foo::Bar'.freeze + + def fast + STRING.delete_prefix('Foo::') + end + + def slow + STRING.sub(/\AFoo::/, '') + end + + Benchmark.ips do |x| + x.report("String#delete_prefix") { fast } + x.report('String#sub') { slow } + x.compare! + end +end From efca7f6793c1a59b5add4007ec7fae363c311eb5 Mon Sep 17 00:00:00 2001 From: Bart de Water Date: Tue, 3 Apr 2018 09:20:36 -0400 Subject: [PATCH 2/2] CI against Ruby 2.5 Add Travis workaround for Bundler 1.16.1 and Rubygems 2.7.3 --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index c74d180..bf5bc41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,12 @@ sudo: false cache: bundler bundler_args: --retry=3 --jobs=3 language: ruby +before_install: + # https://github.com/travis-ci/travis-ci/issues/8978#issuecomment-354036443 + - gem update --system + - gem install bundler rvm: + - 2.5.1 - 2.4.3 - 2.3.0 - 2.1.8