| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
| |
For better or worse, anonymous `*` args will allocate arrays. Ideally,
the interpreter would optimize away this allocation. However, given the
number of times we call `html_safe` it seems worth the shedding idealism
and going for performance. This line was the top allocation spot for a
scaffold (and presumably worse on real applications).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is a reaction to a [bug] we hit in web-console. The cause of it was
a `Kernel` extension called `#console` that was public and was fighting
over Railties with console block to be run on `rails console`. We solved
it by making the method private. We did that through `module_function`
so `::Kernel.console` can be invoked even in `BasicObject`.
I'm proposing to make most of the core Active Support `Kernel`
extensions `module_function` as well. Those are currently public and we
are polluting every `Object` public interface with them.
```ruby
>> Object.new.respond_to? :silence_warnings
=> true
>> Object.new.respond_to? :with_warnings
=> true
>> Object.new.respond_to? :enable_warnings
=> true
>> Object.new.respond_to? :suppress
=> true
``
Some extensions like `Kernel#class_eval` should be public, but most of
them don't really need to be.
[bug]: https://github.com/rails/web-console/issues/184
|
|
|
|
| |
[ci-skip]
|
|
|
|
|
|
|
| |
[ci skip]
Fixes #20808
[Vipul A M & Julio Lopez]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Time.use_zone method will only affect ActiveSupport::TimeWithZone
instances created inside of the block passed to Time.use_zone. This
could be confusing when fetching a model and then reading the attribute
before the block and it not changing afterwards because Active Record
caches the conversion from the database value.
Since changing the behavior of Active Record to recreate the value on
every attribute read is an expensive operation the best we can do is
to document the issue.
Fixes #23195.
[ci skip]
|
| |
|
|\
| |
| | |
Add a missing require to ActiveSupport::NumericWithFormat
|
| | |
|
|/ |
|
| |
|
| |
|
|
|
| |
We went back to `Thread.current[]` in 33e11e59.
|
|
|
|
|
|
| |
accessors"
This reverts commit 301f43820562c6a70dffe30f4227ff0751f47d4f per @matthewd on https://github.com/rails/rails/pull/22630/files#r47997074
|
|
|
|
|
|
|
|
| |
We call the thread variable accessors on `Thread.current`, which matches Ruby's
documentation:
http://ruby-doc.org/core-2.2.0/Thread.html#method-i-thread_variable_get
Fix these to stay `current` ( ͡° ͜ʖ ͡°)
|
|
|
|
| |
[ci skip]
|
|
|
|
| |
[ci skip]
|
| |
|
| |
|
|
|
|
| |
class and module variables that live per-thread
|
|\
| |
| | |
Use Module.prepend instead of alias_method for Range#to_s
|
| | |
|
| | |
|
|/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fixes #22376.
JRuby 9.0.5.0 will support ObjectSpace.each_object against a
class's singleton class, since that's essentially just walking an
internal subclasses structure we already maintain. This test was
too narrow, requiring that each_object support an arbitrary class
but only actually needing it to work against a class's singleton.
This improves performance of Class.descendants by nearly two orders
of magnitude when run against JRuby 9.0.5.0:
```ruby
5.times { puts Benchmark.measure { 100_000.times { Numeric.descendants } } }
```
Before:
```
11.510000 0.140000 11.650000 ( 10.082384)
9.990000 0.020000 10.010000 ( 9.931233)
10.520000 0.040000 10.560000 ( 10.502978)
10.290000 0.030000 10.320000 ( 10.276027)
10.000000 0.030000 10.030000 ( 9.942429)
```
After:
```
1.380000 0.040000 1.420000 ( 0.365850)
0.210000 0.000000 0.210000 ( 0.149574)
0.180000 0.020000 0.200000 ( 0.141094)
0.140000 0.000000 0.140000 ( 0.140634)
0.190000 0.010000 0.200000 ( 0.147962)
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Not only does this make for simpler, more obvious code, it's also more performant:
require 'benchmark/ips'
module Enumerable
def old_sum(identity = 0, &block)
if block_given?
map(&block).old_sum(identity)
else
inject { |sum, element| sum + element } || identity
end
end
def new_sum(identity = 0, &block)
if block_given?
map(&block).new_sum(identity)
else
inject(:+) || identity
end
end
end
summable = (1..100).to_a # sum is 5050
Benchmark.ips do |x|
x.report("old_sum") { summable.old_sum }
x.report("new_sum") { summable.new_sum }
x.compare!
end
# Calculating -------------------------------------
# old_sum 10.674k i/100ms
# new_sum 14.542k i/100ms
# -------------------------------------------------
# old_sum 117.350k (± 7.1%) i/s - 587.070k
# new_sum 154.712k (± 3.8%) i/s - 785.268k
#
# Comparison:
# new_sum: 154712.1 i/s
# old_sum: 117350.0 i/s - 1.32x slower
More benchmarks [here](https://gist.github.com/tjschuck/b3fe4e8c812712376648), including summing strings and passing blocks. The performance gains are less for those, but this version still always wins.
|
|\
| |
| | |
Add days_in_year method to Time class
|
| | |
|
|/ |
|
|\
| |
| | |
Parameterize with options to preserve the case of string
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Added test cases
Using kwargs instead of three seperate functions
Updated parameterize in transliterate.rb
Updated parameterize in transliterate.rb
Added deprecation warnings and updating RDoc+Guide
Misspelled separtor. Fixed.
Deprecated test cases and added support to parameterize with keyword parameters
Squashing commits.
Fixed test cases and added deprecated test cases
Small changes to Gemfile.lock and CHANGELOG
Update Gemfile.lock
|
|\ \
| |/
|/| |
Return a sized Enumerator from Hash#transform_values{!}
|
| | |
|
|\ \
| | |
| | |
| | |
| | | |
`HashWithIndifferentAccess.new` respects the default value or proc on
objects that respond to `#to_hash`
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
objects that respond to `#to_hash`.
Builds on the work of #12550 where `.new` will convert the object (that respond to `#to_hash`) to a hash and
add that hash's keys and values to itself.
This change will also make `.new` respect the default value or proc of objects that respond to `#to_hash`.
In other words, this `.new` behaves exactly like `.new_from_hash_copying_default`.
`.new_from_hash_copying_default` now simply invokes `.new` and any references to `.new_from_hash_copying_default`
are replaced with `.new`.
Added tests confirm behavior.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Before this commit `Module#redefine_method` always changes
visibility of redefined method to `public`.
This commit changes behavior of Module#redefine_method` to
keep method visibility.
|
| | |
| | |
| | |
| | |
| | | |
In later code examples, it is better to write how `Module#anonymous?`
works.
|
| | | |
|
| | |
| | |
| | |
| | |
| | | |
This is primarily to fix method redefinition warnings in class_attribute
but may be of use in other places where we define singleton methods.
|
|\ \ \
| | | |
| | | |
| | | | |
Handle invalid UTF-8 strings when HTML escaping
|
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | | |
Use `ActiveSupport::Multibyte::Unicode.tidy_bytes` to handle invalid UTF-8
strings in `ERB::Util.unwrapped_html_escape` and `ERB::Util.html_escape_once`.
Prevents user-entered input passed from a querystring into a form field from
causing invalid byte sequence errors.
|
|\ \ \ \
| | | | |
| | | | | |
Use Module.prepend instead of alias_method and unify behavior of all Numeric extensions
|
| | | | |
| | | | |
| | | | |
| | | | | |
alias_method
|
|\ \ \ \ \
| | | | | |
| | | | | | |
ActiveSupport: Fixing issue when delegating to methods named "block", "args", or "arg"
|
| | | | | | |
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
The default timestamp used for AR is `updated_at` in nanoseconds! (:nsec) This causes issues on any machine that runs an OS that supports nanoseconds timestamps, i.e. not-OS X, where the cache_key of the record persisted in the database (milliseconds precision) is out-of-sync with the cache_key in the ruby VM.
This commit adds:
A test that shows the issue, it can be found in the separate file `cache_key_test.rb`, because
- model couldn't be defined inline
- transactional testing needed to be turned off to get it to pass the MySQL tests
This seemed cleaner than putting it in an existing testcase file.
It adds :usec as a dateformat that calculates datetime in microseconds
It sets precision of cache_key to :usec instead of :nsec, as no db supports nsec precision on timestamps
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
`each_with_object` allocates an array for each kv pair. Switching to
the slightly more verbose but less allocatey `each_pair` eliminates
array allocations. Eliminating this allocation returns AR objects to
have constant array allocations regardless of the number of columns the
object has.
Here is test code:
```ruby
require 'active_record'
class Topic < ActiveRecord::Base
end
20.times do |i|
Process.waitpid fork {
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Base.connection.instance_eval do
create_table(:topics) do |t|
t.string :title, limit: 250
t.string :author_name
t.string :author_email_address
t.string :parent_title
t.string :type
t.string :group
i.times do |j|
t.string :"aaa#{j}"
end
t.timestamps null: true
end
end
ObjectSpace::AllocationTracer.setup(%i{type})
Topic.create title: "aaron" # heat cache
result = ObjectSpace::AllocationTracer.trace do
10.times do |i|
Topic.create title: "aaron #{i}"
end
end
puts "#{Topic.columns.length},#{(result.find { |k,v| k.first == :T_ARRAY }.last.first / 10)}"
}
end
```
Before this commit:
```
9,166
10,167
11,168
12,169
13,170
14,171
15,172
16,173
17,174
18,175
19,176
20,177
21,178
22,179
23,180
24,181
25,182
26,183
27,184
28,185
```
After:
```
9,157
10,157
11,157
12,157
13,157
14,157
15,157
16,157
17,157
18,157
19,157
20,157
21,157
22,157
23,157
24,157
25,157
26,157
27,157
28,157
```
Left side is the number of columns, right is the number of allocations
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
deep_dup'ing a hash will dup the keys as well as the values. Since
string keys from the source hash will be frozen, and the dup'd objects
are immediately dup'd and frozen on insert in to the hash, the end user
will only ever see two frozen strings. Since the strings are immutable,
this commit just cheats a little and reuses the immutable strings.
Just to reiterate, before this commit, deep duping a hash that looks
like this: `{ "foo" => "bar" }` will generate two new instances of
"foo". One is created when `deep_dup` is called on "foo", and the other
is created when the newly allocated "foo" string is inserted in to the
hash. The user never sees the intermediate "foo", and both copies of
"foo" that the user *can* access will be frozen, so in this case we just
reuse the existing frozen key.
The upshot is that after this change, string allocations on AR
allocations become constant regardless of the number of columns the
model has.
```ruby
require 'active_record'
class Topic < ActiveRecord::Base
end
20.times do |i|
Process.waitpid fork {
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Base.connection.instance_eval do
create_table(:topics) do |t|
t.string :title, limit: 250
t.string :author_name
t.string :author_email_address
t.string :parent_title
t.string :type
t.string :group
i.times do |j|
t.integer :"aaa#{j}"
end
t.timestamps null: true
end
end
ObjectSpace::AllocationTracer.setup(%i{type})
Topic.create title: "aaron" # heat cache
result = ObjectSpace::AllocationTracer.trace do
10.times do |i|
Topic.create title: "aaron #{i}"
end
end
puts "#{Topic.columns.length},#{(result.find { |k,v| k.first == :T_STRING }.last.first / 10)}"
}
end
```
If you run the above script before this commit, the output looks like
this:
```
[aaron@TC rails (master)]$ be ruby -rallocation_tracer test.rb
9,105
10,107
11,109
12,111
13,113
14,115
15,117
16,119
17,121
18,123
19,125
20,127
21,129
22,131
23,133
24,135
25,137
26,139
27,141
28,143
```
The left column is the number of methods, the right column is the number
of string allocations.
Running against this commit, the output is:
```
[aaron@TC rails (master)]$ be ruby -rallocation_tracer test.rb
9,87
10,87
11,87
12,87
13,87
14,87
15,87
16,87
17,87
18,87
19,87
20,87
21,87
22,87
23,87
24,87
25,87
26,87
27,87
28,87
```
As you can see, there is now only a constant number of strings
allocated, regardless of the number of columns the model has.
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | | |
[ci skip] Fix #seconds_since_midnight documentation output it will al…
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
return floating pointnumber
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
Fix Time.now format in documentation [ci skip]
|