2015-11-11 26 views
1

假设我想使用名为'toad'的库。在功能而不是类中加载包的反响

我可以做(Ruby的伪代码):

require 'toad' 

Class MyClass 
def do_stuff 
    Toad.do_toad_stuff 
end 
... 
end 

但我也可以做

... 
def do_stuff 
    require 'toad' 
    Toad.do_toad_stuff 
end 
... 

比方说,蟾蜍是一个相当小的图书馆。它(真的)关系到我在哪里做?如果它很重要,让我们说这个函数被每次用户访问我的Web应用程序调用几次。

我想我最终会好奇,如果任何优化发生。

回答

1

这就是调用do_stuff的频率的问题。如果只是几次,那么使用里面的require,否则只需要一次。

很容易地测试它:

require 'benchmark' 
require 'json' # require any library, doesn't matter 

n = 1_000_000 

def foo_with_require 
    require 'json' 
    2 + 2 
end 

def foo_without_require 
    2 + 2 
end 

Benchmark.bm(20) do |benchmark| 
    benchmark.report('require each time', 20) do 
    n.times { foo_with_require } 
    end 
    benchmark.report('require once') do 
    n.times { foo_without_require } 
    end 
end 

结果如下:

      user  system  total  real 
require each time  2.260000 0.010000 2.270000 ( 2.273471) 
require once   0.080000 0.010000 0.090000 ( 0.079403) 

所以仅需一次是快约30倍,当函数体是2 + 2一样简单,但是如果你的函数做了更有意义的事情,那么这个差别就可以忽略不计。

1

几个百分点:

  1. require 'toad'的方法内没有改变的事实,它会加载常数(例如模块)和全局到正在运行的程序的(全局)范围。
  2. require会记住它已经加载的文件(请参阅$LOADED_FEATURES),并且只会加载一次唯一的文件路径。
  3. 要延迟需要文件直到有必要这样做,您可以使用autoload(由于线程安全性,它已被弃用,但已解决,但它仍是内核的一部分),如下所示:

    class MyClass 
        autoload :Toad, 'toad' 
        ... 
    end