Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Rails 3.2.6 caching is inefficient on Windows #7254

Closed
simonjsmithuk opened this Issue · 4 comments

3 participants

@simonjsmithuk

Using jruby 1.7, Windows 7, Rails 3.2.6

When using config.reload_classes_only_on_change = true the checking of whether to reload a class takes a long time. This is likely as much a windows Issue as it is a Rails Issues, however it may be feasible to work around the issue.

The Issue:

On each request, including simple image requests, the file structure is scanned to see if any files have been added or updated. This scan is very slow on Windows. It is fine on the Mac and Linux.

The following line takes about 1/2 second per call with only about 10 folders in the list.

https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/file_update_checker.rb#L99

    def updated_at #:nodoc:
      @updated_at || begin
        all = []
        all.concat @files.select { |f| File.exists?(f) }
        all.concat Dir[@glob] if @glob     #THIS LINE IS VERY SLOW
        all.map { |path| File.mtime(path) }.max || Time.at(0)
      end
    end

A possible solution is to cache the folders and only update them to include new files after a few seconds have elapsed. This code is possibly not thread safe, I am just providing it for an example. A single request that loads 20 images will now take a second or two to load instead of 10 seconds.

    def initialize(files, dirs={}, &block)
      @files = files
      @glob  = compile_glob(dirs)
      @block = block
      @updated_at = nil
      @last_update_at = updated_at
      @check_new_at = Time.now + 5.seconds
      @dir_cache = Dir[@glob] if @glob
    end

    def updated_at #:nodoc:
      @updated_at || begin
        all = []
        all.concat @files.select { |f| File.exists?(f) }
        if !@check_new_at.nil? && Time.now > @check_new_at
          @dir_cache = Dir[@glob] if @glob
          @check_new_at = Time.now + 5.seconds
        end
        all.concat @dir_cache if @dir_cache
        finish = Time.now
        all.map { |path| File.mtime(path) }.max || Time.at(0)
      end     
    end

Once you have the file list (with only 113 file in it on my project) then it is very fast to actually check the file timestamps for changes.

Other comments:

This is about 4 times worse on JRUBY 1.7 than JRUBY 1.6 for me. It is probably related to bug:
http://jira.codehaus.org/browse/JRUBY-6803?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel

If you precompile your assets the problem goes away, but then you have to recompile them when doing development in the view all the time.

On the mac this code is being executed for every image too, it is just that the problem is less severe as it is about 10 times faster. By using this fix the speed is still considerably improved.

Another possibility for my project is to reduce the number of assets by using image strips/sprite sheets. I'll look into this too.

@steveklabnik
Collaborator

Would you be willing to open a pull request up that fixes this? You have the start of an implementation, we could actually discuss it if we have a pull that we can actually try out.

@simonjsmithuk

Added #7745. The code had changed slightly since last time I looked at it so I had to modify it slightly differently.

@steveklabnik
Collaborator

Awesome, thank you! I'll check it out.

@arunagw
Collaborator

Closing this one as #7745 is open for discussion with code.

thanks!

@arunagw arunagw closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.