| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Since we want this flag to be enabled anytime we are running the tests
under JRuby, let's enable this at the Rakefile level so people get the
performance boost on their local checkout.
Moreover, we avoid having to update this particular line anytime the
option changes on the JRuby side.
The only drawback is that we have to define it in every Rakefile but
there's no big deal, this is already the case for other options.
|
| |
| |
| |
| | |
References f92ac24.
|
|\ \
| | |
| | |
| | |
| | | |
phiggins/remove-dynamic-send-on-built-in-callbacks
Reduce allocations when running AR callbacks.
|
| |/
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Inspired by @tenderlove's work in
c363fff29f060e6a2effe1e4bb2c4dd4cd805d6e, this reduces the number of
strings allocated when running callbacks for ActiveRecord instances. I
measured that using this script:
```
require 'objspace'
require 'active_record'
require 'allocation_tracer'
ActiveRecord::Base.establish_connection adapter: "sqlite3",
database: ":memory:"
ActiveRecord::Base.connection.instance_eval do
create_table(:articles) { |t| t.string :name }
end
class Article < ActiveRecord::Base; end
a = Article.create name: "foo"
a = Article.find a.id
N = 10
result = ObjectSpace::AllocationTracer.trace do
N.times { Article.find a.id }
end
result.sort.each do |k,v|
p k => v
end
puts "total: #{result.values.map(&:first).inject(:+)}"
```
When I run this against master and this branch I get this output:
```
pete@balloon:~/projects/rails/activerecord$ git checkout master
M Gemfile
Switched to branch 'master'
pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_before
pete@balloon:~/projects/rails/activerecord$ git checkout remove-dynamic-send-on-built-in-callbacks
M Gemfile
Switched to branch 'remove-dynamic-send-on-built-in-callbacks'
pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_after
pete@balloon:~/projects/rails/activerecord$ diff allocations_before allocations_after
39d38
<
{["/home/pete/projects/rails/activesupport/lib/active_support/callbacks.rb",
81]=>[40, 0, 0, 0, 0, 0]}
42c41
< total: 630
---
> total: 590
```
In addition to this, there are two micro-optimizations present:
* Using `block.call if block` vs `yield if block_given?` when the block was being captured already.
```
pete@balloon:~/projects$ cat benchmark_block_call_vs_yield.rb
require 'benchmark/ips'
def block_capture_with_yield &block
yield if block_given?
end
def block_capture_with_call &block
block.call if block
end
def no_block_capture
yield if block_given?
end
Benchmark.ips do |b|
b.report("block_capture_with_yield") { block_capture_with_yield }
b.report("block_capture_with_call") { block_capture_with_call }
b.report("no_block_capture") { no_block_capture }
end
pete@balloon:~/projects$ ruby benchmark_block_call_vs_yield.rb
Calculating -------------------------------------
block_capture_with_yield
124979 i/100ms
block_capture_with_call
138340 i/100ms
no_block_capture 136827 i/100ms
-------------------------------------------------
block_capture_with_yield
5703108.9 (±2.4%) i/s - 28495212 in 4.999368s
block_capture_with_call
6840730.5 (±3.6%) i/s - 34169980 in 5.002649s
no_block_capture 5821141.4 (±2.8%) i/s - 29144151 in 5.010580s
```
* Defining and calling methods instead of using send.
```
pete@balloon:~/projects$ cat benchmark_method_call_vs_send.rb
require 'benchmark/ips'
class Foo
def tacos
nil
end
end
my_foo = Foo.new
Benchmark.ips do |b|
b.report('send') { my_foo.send('tacos') }
b.report('call') { my_foo.tacos }
end
pete@balloon:~/projects$ ruby benchmark_method_call_vs_send.rb
Calculating -------------------------------------
send 97736 i/100ms
call 151142 i/100ms
-------------------------------------------------
send 2683730.3 (±2.8%) i/s - 13487568 in 5.029763s
call 8005963.9 (±2.7%) i/s - 40052630 in 5.006604s
```
The result of this is making typical ActiveRecord operations slightly faster:
https://gist.github.com/phiggins/e46e51dcc7edb45b5f98
|
|/
|
|
|
|
| |
Hash#keys.each allocates an array of keys; Hash#each_key iterates through the
keys without allocating a new array. This is the reason why Hash#each_key
exists.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
* The assertions in AS::Duration don't actually assert.
* The assertion in Railtie will pass even when `eager_load_namespaces`
doesn't include `AppTemplate::Application` if `Rails.application` is
truthy.
For more details, see here:
* https://github.com/rails/rails/pull/16998
* https://github.com/rails/rails/pull/17000
|
|
|
|
|
| |
Nothing biggie. Skimmed through `ActiveSupport::Concern` docs these days
and this one comment seemed a bit off.
|
|
|
|
| |
Fixes #16956.
|
|\
| |
| | |
Grammar correction in ActiveSupport CHANGELOG [ci skip]
|
| | |
|
|\|
| |
| | |
[ci skip] ActiveSupport CHANGELOG fixes
|
| |
| |
| |
| |
| |
| |
| | |
1. spacing issues
2. spelling correction
3. grammar correction
4. Add missing docs
|
|\ \
| |/
|/|
| |
| |
| |
| |
| |
| | |
Added method `#eql?` to `ActiveSupport::Duration`, in addition to `#==`.
Conflicts:
activesupport/CHANGELOG.md
activesupport/lib/active_support/duration.rb
activesupport/test/core_ext/duration_test.rb
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Currently, the following returns `false`, contrary to expectation:
1.minute.eql?(1.minute)
Adding method `#eql?` will make this behave like expected. Method `#eql?` is
just a bit stricter than `#==`, as it checks whether the argument is also a
uration. Their parts may be different though.
1.minute.eql?(60.seconds) # => true
1.minute.eql?(60) # => false
|
| |
| |
| |
| |
| | |
Ruby 2.2 knows this, and no longer matches it with [[:space:]], so it's
not a good candidate for testing String#squish.
|
| | |
|
| |
| |
| |
| | |
Closes #16392.
|
| | |
|
| |
| |
| |
| |
| | |
Otherwise this will lead to another error later on
when generating a signature:
TypeError (no implicit conversion of nil into String).
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Goals:
1. Default to :random for newly generated applications
2. Default to :sorted for existing applications with a warning
3. Only show the warning once
4. Only show the warning if the app actually uses AS::TestCase
Fixes #16769
|
| |
| |
| |
| |
| |
| | |
Fixes #8015, #9756.
[Fred Wu & Matthew Draper]
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
https://github.com/rails/rails/commit/98b46bf5e201307cae56ee14bf41363a539779c5
did not properly handled out-of-range `:usec`s.
Passing a `:usec` that's out of range now throws an `ArgumentError` as it
should.
Fixes #16759.
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
We're seeing too many failures to believe otherwise.
This reverts commits bc116a55ca3dd9f63a1f1ca7ade3623885adcc57,
cbde413df3839e06dd14e3c220e9800af91e83ab,
bf0a67931dd8e58f6f878b9510ae818ae1f29a3a, and
2440933fe2c27b27bcafcd9019717800db2641aa.
|
|\ \
| | |
| | |
| | |
| | |
| | | |
tgxworld/dont_swallow_error_when_identifying_constant_from_test_name
Do not swallow exception on NameError within constant.
|
| | |
| | |
| | |
| | | |
Fixes https://github.com/rails/rails/issues/9933.
|
|/ / |
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
When we are loading a component and we want to know its version, we are
actually not speaking about the constant but the library itself.
[ci skip]
[Godfrey Chan & Xavier Noria]
|
| |
| |
| |
| | |
This was removed by mistake in 5e51bdd
|
| |
| |
| |
| |
| |
| | |
`try` allocates an array on every call, we should avoid calling it in
hotspots. This reduced AttributeMethodsTest#test_setting_time_zone_aware_attribute_with_string
from 18k allocations to 14k
|
| |
| |
| |
| | |
just needed some tenderloving instance_eval to fit the bill
|
| |
| |
| |
| | |
:trollface:
|
| | |
|
| | |
|
| | |
|
|\ \ |
|
| | |
| | |
| | |
| | | |
Otherwise, it's possible for GC to run in between, and fail the test.
|
| | | |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Since Rubinius is relying on #instance_of? for its definition of #eql?
(http://git.io/MtmbbA) but ActiveSupport::Duration should behave like
is_a? it returns true with `Fixnum`.
Thus, for the moment, the last assertion is failing so we have to skip
this test.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
For the sake of backward-compatibility, we need to make #instance_of?
return true for Fixnum. On the other hand, the method should still
give true for ActiveSupport::Duration itself which was not the case
before.
|
| | | |
|
| |\ \
| | | |
| | | | |
Define the Duration#instance_of? method
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Since Duration is extending from ProxyObject which extends itself from
BasicObject, the Duration object doesn't respond to the #instance_of?
method. Thus, the #method_missing hook get triggered, delegating the
method to its `value` attribute.
However, Rubinius' #eql? definition relies on #instance_of?, thus this
will equal to true with a Fixnum (since its `value` attribute is a
Fixnum) while it should not.
The previous behavior was wrong anyway, no matter the implementation.
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Zero has one digit, but Math.log10(0) returns -Infinity. The method
needs to special-case zero.
The patch adds a regression test that is not clearly related to the
underlying issue because digit_count is private and has no coverage.
Gray area.
This bug was uncovered by 60062cf.
|
| |\ \ \
| | | | |
| | | | | |
Move as/test_test to as/test_case_test
|
| | | | | |
|
| | | | | |
|
| |/ / /
| | | |
| | | |
| | | |
| | | | |
Also moved comment for removal above `unless()` to not confuse RDoc with
the documentation for this method.
|