| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When the autoload_paths start to grows, this methods is quite a hotspot
>> ActiveSupport::Dependencies.autoload_paths.size
=> 49
>> Benchmark.ips { |x| x.report('baseline') { ActiveSupport::Dependencies.loadable_constants_for_path(File.expand_path('app/models/shop')) }}
Calculating -------------------------------------
baseline 90.000 i/100ms
-------------------------------------------------
baseline 1.073k (±20.2%) i/s - 4.950k
After the patch
Calculating -------------------------------------
patched 883.000 i/100ms
-------------------------------------------------
patched 11.050k (±19.7%) i/s - 50.331k
|
|\
| |
| | |
We need stricter locking before we can unload
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Specifically, the "loose upgrades" behaviour that allows us to obtain an
exclusive right to load things while other requests are in progress (but
waiting on the exclusive lock for themselves) prevents us from treating
load & unload interchangeably: new things appearing is fine, but they do
*not* expect previously-present constants to vanish.
We can still use loose upgrades for unloading -- once someone has
decided to unload, they don't really care if someone else gets there
first -- it just needs to be tracked separately.
|
|/
|
|
|
|
| |
That's outside our remit, and dangerous... if a caller has their own
locking to protect against the natural race danger, we'll deadlock
against it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
I wrote a utility that helps find areas where you could optimize your program using a frozen string instead of a string literal, it's called [let_it_go](https://github.com/schneems/let_it_go). After going through the output and adding `.freeze` I was able to eliminate the creation of 1,114 string objects on EVERY request to [codetriage](codetriage.com). How does this impact execution?
To look at memory:
```ruby
require 'get_process_mem'
mem = GetProcessMem.new
GC.start
GC.disable
1_114.times { " " }
before = mem.mb
after = mem.mb
GC.enable
puts "Diff: #{after - before} mb"
```
Creating 1,114 string objects results in `Diff: 0.03125 mb` of RAM allocated on every request. Or 1mb every 32 requests.
To look at raw speed:
```ruby
require 'benchmark/ips'
number_of_objects_reduced = 1_114
Benchmark.ips do |x|
x.report("freeze") { number_of_objects_reduced.times { " ".freeze } }
x.report("no-freeze") { number_of_objects_reduced.times { " " } }
end
```
We get the results
```
Calculating -------------------------------------
freeze 1.428k i/100ms
no-freeze 609.000 i/100ms
-------------------------------------------------
freeze 14.363k (± 8.5%) i/s - 71.400k
no-freeze 6.084k (± 8.1%) i/s - 30.450k
```
Now we can do some maths:
```ruby
ips = 6_226k # iterations / 1 second
call_time_before = 1.0 / ips # seconds per iteration
ips = 15_254 # iterations / 1 second
call_time_after = 1.0 / ips # seconds per iteration
diff = call_time_before - call_time_after
number_of_objects_reduced * diff * 100
# => 0.4530373333993266 miliseconds saved per request
```
So we're shaving off 1 second of execution time for every 220 requests.
Is this going to be an insane speed boost to any Rails app: nope. Should we merge it: yep.
p.s. If you know of a method call that doesn't modify a string input such as [String#gsub](https://github.com/schneems/let_it_go/blob/b0e2da69f0cca87ab581022baa43291cdf48638c/lib/let_it_go/core_ext/string.rb#L37) please [give me a pull request to the appropriate file](https://github.com/schneems/let_it_go/blob/b0e2da69f0cca87ab581022baa43291cdf48638c/lib/let_it_go/core_ext/string.rb#L37), or open an issue in LetItGo so we can track and freeze more strings.
Keep those strings Frozen
![](https://www.dropbox.com/s/z4dj9fdsv213r4v/let-it-go.gif?dl=1)
|
| |
|
|
|
|
|
| |
We don't need to fully disable concurrent requests: just ensure that
loads are performed in isolation.
|
|
|
|
|
|
|
| |
Module#const_defined? accepts constant paths in modern Ruby, we no longer
need our qualified_* extensions.
References #17845.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The check for circular loading should depend on a stack of files being
loaded at the moment, rather than the collection of loaded files.
This showed up indirectly in #16468, where a misspelled helper would
incorrectly result in a circularity error message.
References #16468
|
|
|
|
|
|
|
| |
Ruby's original behaviour is that :
* It only returns a const name, not a qualified aname
* It returns a symbol, not a string
|
| |
|
| |
|
| |
|
|\
| |
| |
| |
| |
| |
| | |
Conflicts:
guides/source/active_record_validations.md
guides/source/api_documentation_guidelines.md
guides/source/configuring.md
|
| |
| |
| |
| | |
kind of exception we should expect for this internal comment.
|
|/
|
|
| |
unexpected circular dependency error
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
#13204]
load_missing_constant is a private method that basically plays the role of const_missing.
This method has an error condition that is surprising: it raises if the class or module
already has the missing constant. How is it possible that if the class of module has
the constant Ruby has called const_missing in the first place?
The answer is that the from_mod argument is self except for anonymous modules, because
const_missing passes down Object in such case (see the comment in the source code of the
patch for the rationale).
But then, it is better to pass down Object *if Object is also missing the constant* and
otherwise err with an informative message right away.
|
| |
|
| |
|
|\
| |
| | |
Allow Pathname for require dependency
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Previously, an autoloaded constant `HTML::SomeClass` would not be marked
as autoloaded by AS::Dependencies. This is because the
`#loadable_constants_for_path` method uses `String#camelize` on the
inferred file path, which in turn means that, unless otherwise directed,
AS::Dependencies watches for loaded constants in the `Html` namespace.
By passing the original qualified constant name to `#load_or_require`,
this inference step is avoided, and the new constant is picked up in the
correct namespace.
|
| | |
|
| | |
|
|/
|
|
|
|
|
|
|
|
|
|
| |
ActiveSupport::Dependencies::Loadable
It is possible under some environments to receive an Exception that is
not extended with Blamable (e.g. JRuby).
ActiveSupport::Dependencies::Loadable#load_dependency blindly call
blame_file! on the exception which throws it's own NoMethodError
exception and hides the original Exception.
This commit fixes #9521
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Summary of the changes:
* Add thread_safe gem.
* Use thread safe cache for digestor caching.
* Replace manual synchronization with ThreadSafe::Cache in Relation::Delegation.
* Replace @attribute_method_matchers_cache Hash with ThreadSafe::Cache.
* Use TS::Cache to avoid the synchronisation overhead on listener retrieval.
* Replace synchronisation with TS::Cache usage.
* Use a preallocated array for performance/memory reasons.
* Update the controllers cache to the new AS::Dependencies::ClassCache API.
The original @controllers cache no longer makes much sense after @tenderlove's
changes in 7b6bfe84f3 and f345e2380c.
* Use TS::Cache in the connection pool to avoid locking overhead.
* Use TS::Cache in ConnectionHandler.
|
|
|
|
|
|
|
|
|
|
| |
Sometimes, on Mac OS X, programmers accidentally press Option+Space
rather than just Space and don’t see the difference. The problem is
that Option+Space writes a non-breaking space (0XA0) rather than a
normal space (0x20).
This commit removes all the non-breaking spaces inadvertently
introduced in the comments of the code.
|
| |
|
|
|
|
|
| |
The method #remove_const does not load the file, so we
can still remove the constant.
|
| |
|
| |
|
|
|
|
|
| |
I have also chosen a variable name that matches the
parameter in the definition of load_missing_constant.
|
|
|
|
| |
Those who say source code should be without comments lie.
|
|
|
|
|
|
|
|
| |
Basically, const_missing had a loop to try parent namespaces
if the constant lookup failed, but at the same time delegated
to load_missing_constant which in turn also walks up parent
namespaces calling const_missing by hand. In the case of missing
constants this results in repeated work in some funky nested way.
|
|
|
|
|
|
|
| |
#{qualified_name}"
Users need to know the ultimate problem here is that AS was
trying to autoload a constant and it failed.
|
|
|
|
|
|
|
|
| |
We need to anchor to remove the extension. In addition to
be the correct way to do that, files in ~/.rbenv get that
.rb removed, so it is a real source of bugs, as reported in
https://github.com/rails/rails/commit/b33700f5580b4cd85379a1dc60fa341ac4d8deb2#commitcomment-1781840
|
|
|
|
|
|
|
| |
Nowadays circular autoloads do not work, but the user gets a NameError
that says some constant is undefined. That's puzzling, because he is
normally trying to autoload a constant he knows can be autoloaded.
With this check we can give a better error message.
|
|
|
|
|
|
|
| |
loaded stores file names without the .rb extension, but search_for_file
returns file names with the extension.
The solution is hackish, but this file needs a revamp.
|
| |
|
| |
|
|
|
|
|
|
|
|
| |
We simplify two things here: First since * is greedy it is enough to go
look for the rightmost ::, no need to ask the regexp engine to match the
rest of the string since we are not validating anything, only capturing.
The second simplification comes from using a look-ahead assertion, that
allows us to have the capture in $&, thus removing the need of a group.
|
|
|
|
|
| |
The new regexp has less work to do, we anchor a fixed string at the end
and need no group.
|
|
|
|
|
|
| |
This argument is there because that's the signature of Kernel#load.
This reverts commit bf3fa34ed0aa33bca3aac9c96165662fe864a7b4.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Ruby does not pass the nesting to const_missing (unfortunately).
That second argument was there in case that changed, Yehuda
sent a patch to MRI
http://bugs.ruby-lang.org/issues/2740
but there is not much movement there and Matz told me in
Amsterdam there was no immediate plan to pass the nesting.
So let's go back to implement what happens now, and if
in the future we get the nesting then we will adapt this.
Double-checked this with Mr Katz.
|
| |
|
|
|
|
|
|
| |
Ruby 2.0.0 implements LoadError#path, but newly raised load errors will
not contain the path information. Replace the error message, copy
blame, and rereaise the same exception object
|