Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update benchmark gems and test on Ruby 3.2 #297

Merged
merged 1 commit into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
matrix:
# Due to https://github.com/actions/runner/issues/849, we have to use
# quotes for '3.0' -- without quotes, CI sees '3' and runs the latest.
ruby: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1, jruby, truffleruby-head]
ruby: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1, 3.2, jruby, truffleruby-head]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -24,7 +24,7 @@ jobs:
- name: Set bundler environment variables
run: |
echo "BUNDLE_WITHOUT=checks:docs" >> $GITHUB_ENV
if: matrix.ruby != 3.1
if: matrix.ruby != 3.2

# Use 'bundler-cache: true' instead of actions/cache as advised:
# * https://github.com/actions/cache/blob/main/examples.md#ruby---bundler
Expand All @@ -40,18 +40,18 @@ jobs:
files: ./coverage/coverage.xml
fail_ci_if_error: true # optional (default = false)
verbose: true # optional (default = false)
if: matrix.ruby == 3.1
if: matrix.ruby == 3.2

- run: bundle exec rubocop
if: matrix.ruby == 3.1
if: matrix.ruby == 3.2

- run: |
bundle exec yard doctest
bundle exec dokaz
if: matrix.ruby == 3.1
if: matrix.ruby == 3.2

- name: Run benchmarks on Ruby 2.7 or 3.1
- name: Run benchmarks on Ruby 2.7 or 3.2
run: |
BUNDLE_GEMFILE=benchmarks/Gemfile bundle install --jobs 4 --retry 3
BUNDLE_GEMFILE=benchmarks/Gemfile bundle exec ruby benchmarks/benchmarks.rb
if: matrix.ruby == '2.7' || matrix.ruby == '3.1'
if: matrix.ruby == '2.7' || matrix.ruby == '3.2'
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.2
3.2.1
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ _No breaking changes!_

**Project enhancements:**

- Updated benchmark results in `README.md` to Ruby 3.1.2 and 2.7.6
- Updated benchmark results in `README.md` to Ruby 3.2.1 and 2.7.7
- Updated `Dry::Core` gem version to 1.0.0 in benchmarks
- Updated `Memery` gem version to 1.4.1 in benchmarks
- Updated `Memoized` gem version to 1.1.1 in benchmarks
- Reorganized `CHANGELOG.md` for improved clarity and completeness
[[#282](https://github.com/panorama-ed/memo_wise/pull/282)]
Expand Down
4 changes: 2 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ end

# Excluded from CI except on latest MRI Ruby, to reduce compatibility burden
group :docs do
gem "dokaz"
gem "redcarpet", "~> 3.5"
gem "dokaz", "~> 0.0.5"
gem "redcarpet", "~> 3.6"
gem "yard", "~> 0.9"
gem "yard-doctest", "~> 0.1"
end
Expand Down
34 changes: 18 additions & 16 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,24 @@ GEM
concurrent-ruby (1.1.9)
diff-lcs (1.5.0)
docile (1.4.0)
dokaz (0.0.4)
dokaz (0.0.5)
ansi
rouge
rouge (~> 4)
slop (~> 3)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
json (2.6.3)
minitest (5.15.0)
parallel (1.21.0)
parser (3.1.1.0)
parallel (1.22.1)
parser (3.2.0.0)
ast (~> 2.4.1)
rack (3.0.0)
rainbow (3.1.1)
rake (13.0.6)
redcarpet (3.5.1)
regexp_parser (2.2.1)
redcarpet (3.6.0)
regexp_parser (2.6.1)
rexml (3.2.5)
rouge (3.28.0)
rouge (4.1.0)
rspec (3.11.0)
rspec-core (~> 3.11.0)
rspec-expectations (~> 3.11.0)
Expand All @@ -60,16 +61,17 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
rspec-support (3.11.0)
rubocop (1.25.1)
rubocop (1.43.0)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.1.0.0)
parser (>= 3.2.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.15.1, < 2.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.24.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.16.0)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.24.1)
parser (>= 3.1.1.0)
rubocop-performance (1.13.2)
rubocop (>= 1.7.0, < 2.0)
Expand All @@ -95,7 +97,7 @@ GEM
slop (3.6.0)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (2.1.0)
unicode-display_width (2.4.2)
values (1.8.0)
webrick (1.7.0)
yard (0.9.28)
Expand All @@ -108,11 +110,11 @@ PLATFORMS
ruby

DEPENDENCIES
dokaz
dokaz (~> 0.0.5)
memo_wise!
panolint!
rake
redcarpet (~> 3.5)
redcarpet (~> 3.6)
rspec (~> 3.11)
simplecov
simplecov-cobertura
Expand Down
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,36 +114,36 @@ For more usage details, see our detailed [documentation](#documentation).

Benchmarks are run in GitHub Actions, and the tables below are updated with every code change. **Values >1.00x represent how much _slower_ each gem’s memoized value retrieval is than the latest commit of `MemoWise`**, according to [`benchmark-ips`](https://github.com/evanphx/benchmark-ips) (2.9.2).

Results using Ruby 3.1.2:
Results using Ruby 3.2.1:

|Method arguments|`Dry::Core`\* (0.7.1)|`Memery` (1.4.0)|
|Method arguments|`Dry::Core`\* (1.0.0)|`Memery` (1.4.1)|
|--|--|--|
|`()` (none)|1.14x|13.06x|
|`(a)`|1.22x|7.24x|
|`(a, b)`|1.17x|6.79x|
|`(a:)`|1.33x|16.68x|
|`(a:, b:)`|1.24x|13.73x|
|`(a, b:)`|1.16x|13.58x|
|`(a, *args)`|0.84x|1.95x|
|`(a:, **kwargs)`|0.84x|3.41x|
|`(a, *args, b:, **kwargs)`|0.75x|2.08x|
|`()` (none)|0.55x|3.66x|
|`(a)`|1.55x|8.09x|
|`(a, b)`|1.21x|6.09x|
|`(a:)`|1.42x|13.29x|
|`(a:, b:)`|1.17x|10.04x|
|`(a, b:)`|1.18x|10.32x|
|`(a, *args)`|0.78x|1.54x|
|`(a:, **kwargs)`|0.80x|2.22x|
|`(a, *args, b:, **kwargs)`|0.71x|1.38x|

\* `Dry::Core`
[may cause incorrect behavior caused by hash collisions](https://github.com/dry-rb/dry-core/issues/63).

Results using Ruby 2.7.6 (because these gems raise errors in Ruby 3.x):
Results using Ruby 2.7.7 (because these gems raise errors in Ruby 3.x):

|Method arguments|`DDMemoize` (1.0.0)|`Memoist` (0.16.2)|`Memoized` (1.1.1)|`Memoizer` (1.0.3)|
|--|--|--|--|--|
|`()` (none)|24.72x|2.36x|27.25x|2.88x|
|`(a)`|22.13x|14.22x|23.37x|12.54x|
|`(a, b)`|17.70x|12.04x|17.69x|10.66x|
|`(a:)`|31.24x|24.94x|26.47x|22.97x|
|`(a:, b:)`|25.76x|20.78x|21.41x|19.47x|
|`(a, b:)`|23.97x|19.53x|19.91x|18.01x|
|`(a, *args)`|3.23x|2.21x|3.34x|1.98x|
|`(a:, **kwargs)`|2.92x|2.45x|2.57x|2.24x|
|`(a, *args, b:, **kwargs)`|2.22x|1.88x|1.99x|1.78x|
|`()` (none)|23.65x|2.38x|27.26x|2.71x|
|`(a)`|22.27x|15.66x|22.82x|13.61x|
|`(a, b)`|18.72x|13.85x|18.79x|12.42x|
|`(a:)`|31.54x|25.56x|26.57x|23.88x|
|`(a:, b:)`|27.56x|22.78x|23.67x|21.43x|
|`(a, b:)`|26.16x|21.75x|22.45x|20.63x|
|`(a, *args)`|3.10x|2.32x|3.25x|2.02x|
|`(a:, **kwargs)`|2.82x|2.37x|2.59x|2.23x|
|`(a, *args, b:, **kwargs)`|2.14x|1.84x|1.97x|1.75x|

You can run benchmarks yourself with:

Expand Down
6 changes: 3 additions & 3 deletions benchmarks/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ source "https://rubygems.org"

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby ">= 2.7.6"
ruby ">= 2.7.7"

gem "benchmark-ips", "2.10.0"

if RUBY_VERSION > "3"
gem "dry-core", "0.7.1"
gem "memery", "1.4.0"
gem "dry-core", "1.0.0"
gem "memery", "1.4.1"
else
gem "ddmemoize", "1.0.0"
gem "memoist", "0.16.2"
Expand Down
13 changes: 7 additions & 6 deletions lib/memo_wise.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require "set"
# Disable RuboCop here because Ruby < 3.2 does not load `set` by default.
require "set" # rubocop:disable Lint/RedundantRequireStatement

require "memo_wise/internal_api"
require "memo_wise/version"
Expand Down Expand Up @@ -30,12 +31,12 @@ module MemoWise
# [calling the original](https://medium.com/@jeremy_96642/ruby-method-auditing-using-module-prepend-4f4e69aacd95)
# constructor.
#
# - **Q:** Why is [Module#prepend](https://ruby-doc.org/core-3.1.0/Module.html#method-i-prepend)
# - **Q:** Why is [Module#prepend](https://ruby-doc.org/3.2.1/Module.html#method-i-prepend)
# important here
# ([more info](https://medium.com/@leo_hetsch/ruby-modules-include-vs-prepend-vs-extend-f09837a5b073))?
# - **A:** To set up *mutable state* inside the instance, even if the original
# constructor will then call
# [Object#freeze](https://ruby-doc.org/core-3.1.0/Object.html#method-i-freeze).
# [Object#freeze](https://ruby-doc.org/3.2.1/Object.html#method-i-freeze).
#
# This approach supports memoization on frozen (immutable) objects -- for
# example, classes created by the
Expand Down Expand Up @@ -84,7 +85,7 @@ def initialize(#{all_args})
# @param target [Class]
# The `Class` into to prepend the MemoWise methods e.g. `memo_wise`
#
# @see https://ruby-doc.org/core-3.1.0/Module.html#method-i-prepended
# @see https://ruby-doc.org/3.2.1/Module.html#method-i-prepend
#
# @example
# class Example
Expand All @@ -99,7 +100,7 @@ class << target
#
# This is necessary in addition to the `#initialize` method definition
# above because
# [`Class#allocate`](https://ruby-doc.org/core-3.1.0/Class.html#method-i-allocate)
# [`Class#allocate`](https://ruby-doc.org/3.2.1/Class.html#method-i-allocate)
# bypasses `#initialize`, and when it's used (e.g.,
# [in ActiveRecord](https://github.com/rails/rails/blob/a395c3a6af1e079740e7a28994d77c8baadd2a9d/activerecord/lib/active_record/persistence.rb#L411))
# we still need to be able to access MemoWise's instance variable. Despite
Expand Down Expand Up @@ -254,7 +255,7 @@ def #{method_name}(#{MemoWise::InternalAPI.args_str(method)})
)
end

# Override [Module#instance_method](https://ruby-doc.org/core-3.1.0/Module.html#method-i-instance_method)
# Override [Module#instance_method](https://ruby-doc.org/3.2.1/Module.html#method-i-instance_method)
# to proxy the original `UnboundMethod#parameters` results. We want the
# parameters to reflect the original method in order to support callers
# who want to use Ruby reflection to process the method parameters,
Expand Down
3 changes: 1 addition & 2 deletions spec/memo_wise_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@
end
end

shared_examples "handles memoized/non-memoized methods with the same name at different "\
"scopes" do
shared_examples "handles memoized/non-memoized methods with the same name at different scopes" do
context "with non-memoized method with same name as memoized method" do
context "when methods have no arguments" do
it "does not memoize the non-memoized method" do
Expand Down
6 changes: 3 additions & 3 deletions spec/prepending_initializer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Class.new do
prepend MemoWise

def initialize(arg); end
def initialize(arg); end # rubocop:disable Style/RedundantInitialize
end
end

Expand All @@ -21,7 +21,7 @@ def initialize(arg); end
Class.new do
prepend MemoWise

def initialize(kwarg:); end
def initialize(kwarg:); end # rubocop:disable Style/RedundantInitialize
end
end

Expand All @@ -35,7 +35,7 @@ def initialize(kwarg:); end
Class.new do
prepend MemoWise

def initialize(arg, kwarg:); end
def initialize(arg, kwarg:); end # rubocop:disable Style/RedundantInitialize
end
end

Expand Down
2 changes: 1 addition & 1 deletion spec/proxying_original_method_params_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Class.new do
prepend MemoWise

def initialize(foo, bar:); end
def initialize(foo, bar:); end # rubocop:disable Style/RedundantInitialize

DefineMethodsForTestingMemoWise.define_methods_for_testing_memo_wise(
target: self,
Expand Down