| Commit message (Collapse) | Author | Age | Files | Lines |
|\
| |
| |
| |
| | |
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.
|
|/
|
|
| |
@column_names_with_alias, @dynamic_methods_hash, @time_zone_column_names, and @cached_time_zone
|
|
|
|
| |
- middlware -> middleware
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Benchmark:
```ruby
require 'objspace'
require 'active_record'
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
ObjectSpace::AllocationTracer.trace do
N.times { Article.find a.id }
end
ObjectSpace::AllocationTracer.allocated_count_table
table.sort_by { |_,x| x }.each do |k,v|
p k => (v / N)
end
```
|
| |
|
|
|
|
|
|
|
| |
Honoring an overidden `rack.test` allows testing closed connection between
multiple requests. This is useful if you're working on database resiliency, to
ensure the connection is in the expected state from one request to another on
the same worker.
|
|
|
|
| |
[ci skip]
|
|
|
|
|
|
| |
it doesn't work on SQLite3 since it doesn't support truncate, but that's
OK. If you call truncate on the connection, you're now bound to that
database (same as if you use hstore or any other db specific feature).
|
|
|
|
|
|
|
| |
Previously the documentation stated that `primary_key` should be the name of
a *method* that returns the primary key used for the association. This is
incorrect. This changes the documentation to say that the value must be the
name of a column.
|
| |
|
|
|
|
| |
:foreign_key option that's a symbol
|
|
|
|
|
| |
This test has always been green because it uses "assert" and the first
argument is an truthy class/object.
|
| |
|
|\
| |
| |
| | |
ActiveRecord CHANGELOG improvements [skip ci]
|
|/ |
|
|
|
|
|
| |
The hash is now string-keyed, and [_]reflect_on_association calls `to_s` on the
argument anyway.
|
|
|
|
|
|
|
|
|
| |
For now, we will just skip the cache when a non-column key is used in the hash.
If the future, we can probably move some of the logic in PredicateBuilder.expand
up the chain to make caching possible for association queries.
Closes #16903
Fixes #16884
|
|
|
|
|
|
| |
This is pretty lame though, so feel free to send a PR with a better fix! ;)
cc @zev @tenderlove
|
|\
| |
| | |
Update RecordNotFound exception cases to include a message with the
|
| |
| |
| |
| | |
Model that the Record was not found in.
|
|\ \
| | |
| | | |
Updated comment about features of fixtures
|
| | |
| | |
| | |
| | |
| | |
| | | |
- Added a note about some features which are not dependent on
auto-generated ID's.
- [ci skip]
|
|/ / |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
While investigating #16951 I found that another library's monkey-patching of
`Enumerable` was causing the test migrations helper to break when trying to
build the `CREATE DATABASE` statement. The prior approach used `#sum` to build
the string from the options hash.
As the code that combines the options to build the database statement is not
user-facing, using `#inject` here instead will remove the only place where the
database creation/migration code is dependent on ActiveSupport's monkey-patching
of `Enumerable`.
|
| | |
|
|\ \
| | |
| | |
| | |
| | |
| | |
| | | |
Don't autosave unchanged has_one through records
Conflicts:
activerecord/CHANGELOG.md
|
| | | |
|
|\ \ \
| | | |
| | | | |
Allow YAML serialization when using TZ aware attributes
|
| | | | |
|
|\ \ \ \
| |/ / /
|/| | |
| | | |
| | | | |
kongregate/fix-activerecord-deprecated_finders-find-symbol
ActiveRecord deprecated finders are broken in 4.2
|
| |/ /
| | |
| | |
| | |
| | |
| | |
| | | |
Maintain compatibility for:
* ActiveRecord::Base#find(:all)
* ActiveRecord::Base#find(:first)
* ActiveRecord::Base#find(:last)
|
| | | |
|
| | | |
|
|/ /
| |
| |
| |
| |
| | |
Closes #16907.
[Matthew Draper & Yves Senn]
|
|\ \
| | |
| | |
| | | |
Data corruption risk: Roll back open transactions when the running thread is killed.
|
| | | |
|
|\ \ \
| | | |
| | | | |
Improved the error messaging for the DangerousAttributeError exception
|
| | | |
| | | |
| | | |
| | | | |
that the conflict could be because of a conflicting attribute.
|
| | | | |
|
| | | | |
|
| | | |
| | | |
| | | |
| | | | |
Working with two different machines is hard :sweat:
|
|/ / /
| | |
| | |
| | |
| | |
| | | |
[Matthew Draper & Yves Senn]
Closes #16860. (pull request to discuss the implementation)
|
|\ \ \
| | | |
| | | |
| | | | |
Default to sorting user's test cases for now
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
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
|
| | | |
| | | |
| | | |
| | | | |
Dump the standard schema once instead of redoing it per test
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Allows :limit defaults to be changed without pulling the rug out from
under old migrations that omitted :limit because it matched the default
at the time.
|
| | | | |
|
| | | | |
|