Is Autoload Thread-Safe in Ruby 1.9

Is autoload thread-safe in Ruby 1.9?

I don't know about the general case, but repro example from that thread doesn't break in 1.9.1:

autoloaded.rb:

sleep 1
Bar::Foo = 1

autoloader.rb:

module Bar
autoload :Foo, 'autoloaded.rb'
end

t1 = Thread.new { Bar::Foo }
t2 = Thread.new { Bar::Foo }
t1.join; t2.join

Autoloading ruby gem warning, may be causing Heroku application error?

WEBrick is a Ruby webserver designed for development and not recommended for production use. It's also multithreaded.

Try adding gem "thin" to your Gemfile. Heroku will then use Thin as the server, which is not multithreaded (by default though it has a threaded option), and your non thread-safe way will probably go away.

autoload with namespaces/submodules

You need to pass a symbol to autoload (probably a typo in your question), and call it on the parent of the constant, like:

App.autoload :ModuleA, "app/module_a"

Note that this works for nested levels too. Say that in app/module_a you have:

module App::ModuleA
autoload :Inner, "path/to/inner"
end

When Ruby encounters App::ModuleA::Inner, it will first attempt to access ModuleA, succeed by autoloading it, and only then attempt Inner, which succeeds also because it now knows where to autoload it.

Autoloading classes in Ruby without its `autoload`

This was raised in a Rails ticket some time ago and when I investigated it there appeared to be no way round it. The problem is that Ruby will search the ancestors before calling const_missing and since all classes have Object as an ancestor then any top-level constants will always be found. If you can restrict yourself to only using modules for namespacing then it will work since they do not have Object as an ancestor, e.g:

>> class A; end
>> class B; end
>> B::A
(irb):3: warning: toplevel constant A referenced by B::A

>> B.ancestors
=> [B, Object, Kernel, BasicObject]

>> module C; end
>> module D; end
>> D::C
NameError: uninitialized constant D::C

>> D.ancestors
=> [D]

sass' in a non thread-safe way

have you tried doing this in Gemfile?

gem "sass", :require => 'sass'

this is an explicit call, without using initializers. by the way consider that you're using a rc1 release.

confusing about autoload_paths vs eager_load_paths in rails 4

Author of the linked article here. Here's an attempt to clear up the confusion, going off of @fkreusch's answer.

In Ruby you have to require every .rb file in order to have its code run. However, notice how in Rails you never specifically require any of your models, controllers, or other files in the app/ dir. Why is that? That's because in Rails app/* is in autoload_paths. This means that when you run your rails app in development (for example via rails console) — none of the models and controllers are actually required by ruby yet. Rails uses special magical feature of ruby to actually wait until the code mentions a constant, say Book, and only then it would run require 'book' which it finds in one of the autoload_paths. This gives you faster console and server startup in development, because nothing gets required when you start it, only when code actually needs it.

Now, this behavior is good for local development, but what about production? Imagine that in production your server does the same type of magical constant loading (autoloading). It's not the end of the world really, you start your server in production, and people start browsing your pages slightly slower, because some of the files will need to be autoloaded. Yes, it's slower for those few initial requests, while the server "warms up", but it's not that bad. Except, that's not the end of the story.

If you are running on ruby 1.9.x (if I recall correctly), then auto-requiring files like that is not thread safe. So if you are using a server like puma, you will run into problems. Even if you aren't using a multi-threaded server, you are still probably better off having your whole application get required "proactively", on startup. This means that in production, you want every model, every controller, etc all fully required as you start your app, and you don't mind the longer startup time. This is called eager loading. All ruby files get eagerly loaded, get it? But how can you do that, if your rails app doesn't have a single require statement? That's where eager_load_paths come in. Whatever you put in them, all the files in all the directories underneath those paths will be required at startup in production. Hope this clears it up.

It's important to note that eager_load_paths are not active in development environment, so whatever you put in them will not be eagerly required immediately in development, only in production.

It's also important to note that just putting something into autoload_paths will not make it eager-loaded in production. Unfortunately. You have to explicitly put it into eager_load_paths as well.

Another interesting quirk is that in every rails app, all directories under app/ are automatically in both autoload_paths and eager_load_paths, meaning that adding a directory there requires no further actions.



Related Topics



Leave a reply



Submit