为什么参数化在第一次执行时会非常慢

qic*_*_he 5 ruby ruby-on-rails

我有以下代码,基本上将参数化的执行时间乘以:

require 'active_support'
require 'active_support/core_ext'

for x in 0..10
  ss = Array.new(1000, "Book Author Title")
  st = Time.now
  ss = ss.map {|s| s.parameterize}
  et = Time.now
  p "parameterize 1000 simple strings takes #{'%.4f' % ((et - st)*1000)} milliseconds"
end
# p ss
Run Code Online (Sandbox Code Playgroud)

但是我得到了输出,例如:

"parameterize 1000 simple strings takes 219.5780 milliseconds"
"parameterize 1000 simple strings takes 74.3870 milliseconds"
"parameterize 1000 simple strings takes 73.9830 milliseconds"
"parameterize 1000 simple strings takes 76.3160 milliseconds"
"parameterize 1000 simple strings takes 65.7620 milliseconds"
"parameterize 1000 simple strings takes 78.5280 milliseconds"
"parameterize 1000 simple strings takes 89.2950 milliseconds"
"parameterize 1000 simple strings takes 90.6750 milliseconds"
"parameterize 1000 simple strings takes 93.8500 milliseconds"
"parameterize 1000 simple strings takes 74.2330 milliseconds"
"parameterize 1000 simple strings takes 86.2160 milliseconds"
Run Code Online (Sandbox Code Playgroud)

第一次执行它比接下来要花费更多的钱,我想知道为什么会这样。

感谢大家!

ucp*_*uzz 4

简短回答:\n 第一次调用 ActiveSupport::Inflector#parametrize 最终会在此处加载 unicode 数据库。这增加了 70 多毫秒的开销,也是第一次调用速度较慢的主要原因。

\n\n

长答案:"Book Author Title\xe2\x80\x9d.parametrize \n由于以下原因,第一次调用很慢:

\n\n
    \n
  1. 加载 unicode 数据库并进行规范化需要 70 多毫秒
  2. \n
  3. 第一次调用时的 I18n.transliterate("Book Author Title") 会在 10-15 毫秒内翻译并缓存响应。后续调用返回缓存值,需要 0.002 毫秒。
  4. \n
\n\n

以下是加载 unicode 数据库的调用顺序:

\n\n
ActiveSupport::Inflector.parametrize ->\n ActiveSupport::Inflector.transliterate ->\n  ActiveSupport::Multibyte::Unicode.normalize ->\n   https://github.com/rails/rails/blob/v5.2.3/activesupport/lib/active_support/multibyte/unicode.rb#L340\n
Run Code Online (Sandbox Code Playgroud)\n\n

尝试下面的代码片段来验证。

\n\n
require \'active_support\'\nrequire \'active_support/core_ext\'\ndef benchmark_normalize(s)\n  st = Time.now\n  ts = ActiveSupport::Multibyte::Unicode.normalize(s, :c)\n  et = Time.now\n  p "takes #{\'%.4f\' % ((et - st)*1000)} milliseconds"\nend\nbenchmark_normalize("Book Author Title")\n
Run Code Online (Sandbox Code Playgroud)\n