在函数而不是 class 中加载包的影响
Repercussion of loading packages within a function instead of class
假设我想使用一个名为 '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
...
假设 toad 是一个相当小的图书馆。我在哪里做(真的)重要吗?如果重要的话,假设每次用户访问我的 Web 应用程序都会调用此函数几次。
我想我最终很好奇是否会发生任何优化。
这就是 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)
所以当函数体像 2 + 2
一样简单时,只需要一次大约快 30 倍,但是如果你的函数做任何更有意义的事情,差异将可以忽略不计。
几点:
- 将
require 'toad'
放入方法中并不会改变它将常量(例如模块)和全局变量加载到 运行 程序的(全局)范围内的事实。
require
会记住它已经加载的文件(参见 $LOADED_FEATURES
)并且只会加载唯一的文件路径一次。
要推迟对文件的要求,直到有必要这样做,您可以使用 autoload
(由于线程安全,它曾一度被弃用,但已经解决并且它仍然是内核的一部分),如下所示:
class MyClass
autoload :Toad, 'toad'
...
end
假设我想使用一个名为 '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
...
假设 toad 是一个相当小的图书馆。我在哪里做(真的)重要吗?如果重要的话,假设每次用户访问我的 Web 应用程序都会调用此函数几次。
我想我最终很好奇是否会发生任何优化。
这就是 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)
所以当函数体像 2 + 2
一样简单时,只需要一次大约快 30 倍,但是如果你的函数做任何更有意义的事情,差异将可以忽略不计。
几点:
- 将
require 'toad'
放入方法中并不会改变它将常量(例如模块)和全局变量加载到 运行 程序的(全局)范围内的事实。 require
会记住它已经加载的文件(参见$LOADED_FEATURES
)并且只会加载唯一的文件路径一次。要推迟对文件的要求,直到有必要这样做,您可以使用
autoload
(由于线程安全,它曾一度被弃用,但已经解决并且它仍然是内核的一部分),如下所示:class MyClass autoload :Toad, 'toad' ... end