Upgrade to Pro — share decks privately, control downloads, hide ads and more …

环境变量为何能让 Ruby 快十倍

8002c84eb4c18170632f8fb7efb09288?s=47 Minqi Pan
September 24, 2016

环境变量为何能让 Ruby 快十倍

Why environment variables could slow down your Ruby scripts for 10 times

https://www.youtube.com/watch?v=A1V-vZklVLY

8002c84eb4c18170632f8fb7efb09288?s=128

Minqi Pan

September 24, 2016
Tweet

Transcript

  1. 辘हݒᰁ
 ԅ֜胼ᦏ Ruby 盠܈狝 笳碭ቡ

  2. य़疑অ, ౯ݞ笳碭ቡ github.com/pmq20 twitter @psvr

  3. None
  4. None
  5. None
  6. GitLab 耬ᵅ #15452 “On average it seems to take around

    13 seconds to cherry-pick commits for GitLab CE. Most of the time appears to be spent in GitHooksService#execute (around 10 seconds on average).” – Yorick Peterse
  7. GitLab 耬ᵅ #15452 https://gitlab.com/gitlab-org/gitlab-ce/issues/15452

  8. GitLab 耬ᵅ #15452 https://gitlab.com/gitlab-org/gitlab-ce/issues/15452 system(…pre-receive…) 
 system(…update…) system(…post-receive…)

  9. Kernel#system

  10. ಗᤈ෸ᳵᕅ 60ms ጱ Ruby 郥๜

  11. አ system ݄᧣疰ݒ౮ԧ 600ms

  12. 簁ᘒ unsetenv_others ݢ盵瓰蝧ଶ

  13. ٌਙᥡ疗ᕮຎ • “./update” ஠ᶳԅ Ruby 纷ଧ牧覍 Ruby 犋瓰ሿ • “./update”

    ݢ覍ଉᓌܔ牧 Hello World ܨݢ瓰ሿ
  14. [demo]

  15. unsetenv_others ฎՋԍ牫 • 蟴ᗝฎ玽竃ቘ辘हݒᰁ • ୮ unsetenv_others: true ෸牧霙ᤈक़蟂纷ଧ獮竃ቘ ಅ磪辘हݒᰁ牧ᴻ覍ฎก繊瞲ਧጱݒᰁ

    • ୮ unsetenv_others: false ෸牧犋竃ቘҁ认ᦊᤈԅ҂
  16. gitlab-ce: MR-3939 https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3939

  17. – Yorick Peterse “I'm a bit confused, how does unsetting

    environment variables make things run faster?”
  18. – Douwe Maan “The measurements don't lie, but I'm not

    quite sure why this works either. Can you elaborate?”
  19. चᏐᎣᦩ

  20. ྯӻᬰ纷᮷磪ᛔ૩ጱᆿᬰ纷 ྯӻᬰ纷᮷ฎݚӞӻᬰ纷貉ۖጱ

  21. ྯӻᬰ纷᮷磪ᛔ૩ᇿ缏ጱ辘हݒᰁ

  22. ྯӻᬰ纷᮷磪ᛔ૩ᇿ缏ጱ辘हݒᰁ

  23. ৼᬰ纷՗ᆿᬰ纷Ӿᖀ瞚辘हݒᰁ

  24. ֕ৼᬰ纷犋胼狕硬ᆿᬰ纷ጱ辘हݒᰁ

  25. വᦞ1 辘हݒᰁ鋓ᬰ纷ᕮ๳ᘒ窞犜 ҁshell ฎ IRB ጱᆿᬰ纷҂

  26. വᦞ2 窔ኞৼᬰ纷ݢ皤ᖅᆿᬰ纷辘हݒᰁጱኞ޸珏๗ ҁIRB ฎ shell ጱᆿᬰ纷҂

  27. ᆿᬰ纷磪ߺ犚ݢ綡ጱ辘 हݒᰁ᭳փᕳԧৼᬰ纷牫

  28. BUNDLE_BIN_PATH /Users/pmq20/.rvm/gems/ruby-2.1.8/ gems/bundler-1.12.4/exe/bundle BUNDLE_GEMFILE /Users/pmq20/gitlab-development- kit/gitlab/Gemfile BUNDLE_ORIG_GEM_PATH /Users/pmq20/.rvm/gems/ ruby-2.1.8:/Users/pmq20/.rvm/gems/ ruby-2.1.8@global

    BUNDLE_ORIG_MANPATH /usr/local/man:
  29. GEM_HOME /Users/pmq20/.rvm/gems/ruby-2.1.8 GEM_PATH /Users/pmq20/.rvm/gems/ ruby-2.1.8:/Users/pmq20/.rvm/gems/ ruby-2.1.8@global RUBYLIB /Users/pmq20/.rvm/gems/ruby-2.1.8/ gems/bundler-1.12.4/lib RUBYOPT

    -rbundler/setup
  30. RUBY_VERSION ruby-2.1.8 rvm_bin_path /Users/pmq20/.rvm/bin rvm_path /Users/pmq20/.rvm rvm_prefix /Users/pmq20

  31. ᇨՈ΅͠獮Ͷ牦

  32. GEM_HOME /Users/pmq20/.rvm/gems/ruby-2.1.8 GEM_PATH /Users/pmq20/.rvm/gems/ ruby-2.1.8:/Users/pmq20/.rvm/gems/ ruby-2.1.8@global RUBYLIB /Users/pmq20/.rvm/gems/ruby-2.1.8/ gems/bundler-1.12.4/lib RUBYOPT

    -rbundler/setup
  33. RUBYOPT man ruby

  34. e.g.

  35. ৼᬰ纷ᖀ瞚ԧᆿᬰ纷ጱ RUBYOPT=-rbundler/setup

  36. ᘒ bundler/setup ಗᤈ盄眸 ࢩ種ৼᬰ纷ಗᤈ盄眸

  37. 簁ᘒक़蟂 shell ๚ਧԎᧆݒᰁ

  38. 貉ۖ Rails ݸ಍磪ԧᧆݒᰁ

  39. RUBYOPT=-rbundler/setup ՗֜ᘒ๶牫

  40. ᆿᬰ纷ฎአ bin/rails 貉ۖጱ

  41. bin/rails ᧣አԧ config/boot

  42. config/boot ᧣አԧ bundler/setup

  43. bundler/setup ᦡਧԧ RUBYOPT=-rbundler/setup ࢩ種 bundler/setup ฎٍ磪փ礕௔ጱ bundler ᦏಅ磪 bundler ᓕቘጱᬰ纷ጱৼᬰ纷᮷ᤩ

    bundler ᓕቘ
  44. bundler/setup
 ฎՋԍ牫

  45. bundler/setup ฎӞӻ෈կ

  46. bundler/setup ጱֵአ࣋ว • bin/rails ᧣አԧ bundler/setup • bundle exec *

    ᧣አԧ bundler/setup • bundle show * ᧣አԧ bundler/setup • bundle bin-stubs ጱኞ౮ᇔ᮷᧣አԧ bundler/setup • ࢩ種 bundler/setup پԒฎ Ruby 貉ۖ鉑纷ጱຽ蟴
  47. bundler/setup ጱᦡᦇፓຽ • “make your code see just the dependencies

    that it should see and nothing else” • 矒ګঅ gem ପጱے᫹᪠趥矾ᔱᶲଧ • ᦏ纷ଧ௴অ胼୚አک Gemfile Ӿ瞲ਧጱ粚๜ጱପ • ᘒӬ獡ฎ Gemfile Ӿ๚瞲ਧጱ gem ᮷犋ݢᥠ
  48. Kernel#require • require ‘thing’ • ইຎ ‘thing’ ૪ᕪے᫹鉑牧ಗᤈᕮ๳ • 玽ڞ螁ܲ

    $LOAD_PATH ($:) ತک ‘thing’ ଚے᫹ԏ • 舙ತ犋کڞಲڊ LoadError
  49. rubygems/core_ext/ kernel_require.rb • ᯿碝಑୏ Kernel ଚ remove_method ധԧ :require •

    ᯿碝ਧԎԧ Kernel#require • ᛔ Ruby 1.9 犥๶ RubyGems ฎٖᗝጱଚᛔۖ貉አ • ᛔ Ruby 1.9 犥๶鉖಍ฎ Kernel#require ጱ፥ྋᶎፓ
  50. rubygems/core_ext/ kernel_require.rb • require ‘thing’ • ইຎ ‘thing’ ૪ᕪے᫹鉑牧ಗᤈᕮ๳ •

    玽ڞ螁ܲ $LOAD_PATH ($:) ತک ‘thing’ ଚے᫹ԏ • 玽ڞ՗૪ਞᤰጱ gem Ӿ੔ತ ‘thing’ ଚ಩ᧆ gem ጱ ᪠趥ے獈 $LOAD_PATH ($:) • 舙ತ犋کڞಲڊ LoadError
  51. 牬demo] require pry, edit require

  52. bundler/setup ࣁ狶Ջԍ • ತکӞᕟ粬ਧ粚๜ጱ gem牧玲ڊ犢ժጱ gemspec • ಩ਙժጱ lib/ ፓ趟ጱᕷ੒᪠趥ے獈

    $LOAD_PATH牧 犥׎ Ruby ݢ犥 require ک粬ਧ粚๜ጱ gem • “unpatch”物݄ധ rubygems/core_ext/ kernel_require.rb ጱ鉪ᬋ牧犥׎贶ሿ“獡ฎ Gemfile Ӿ๚瞲ਧጱ gem ᮷犋ݢᥠ”
  53. 牬demo] reverse_rubygems_kernel_mixin

  54. – hooopo “ഝ᧔牧Bundler ޾ Rubygems ᥝݳଚԧ”

  55. – huacnlee “疰ᧆݳଚ牧ݶ遞ጱӳᥜ”

  56. ෸ᳵ᮷݄ߺدԧ牫

  57. Bundler::Resolver.resolve • 臺ᩇԧ踞ጯྺᑁጱಗᤈ෸ᳵ • ತک磧犭ጱ gem ᕟݳ牧ֵ஑犢ժݢჿ᪃粬ਧጱ狅ᩢ ޾ৼ狅ᩢ蹇կҁܨ Gemfile +

    Gemfile.lock҂ • ᬌ獈物Ӟᕟ狅ᩢ蹇կҁܨ Gemfile + Gemfile.lock҂ • ᬌڊ物Ӟᕟ gemspec
  58. Gemfile.lock ጱᦡᦇ௏మ • 薹ຉਠ Gemfile ݸ಩ᕮຎᖨਂӥ๶ጱӞӻ๢ګ • ۱珀 “exact versions

    of all of the gems that you used the last time you know for sure that the application worked” • 犌 npm 2 / npm 3 ᦡᦇ௏మጱ੒穉
  59. Gemfile 犌 Gemfile.lock 
 ݢ胼ڊሿ犋ݶྍ • ࣁ૪磪 Gemfile.lock ጱ眐٭ӥ牧አಁๅ碝ԧ Gemfile

    ᘒဌ磪᯿碝 bundle牧ڞ Gemfile.lock 鉑๗ • 舙羬ᕹ૪磪胼ჿ᪃ Gemfile 碝襑穩ጱ gem牧ڞ貉ۖ ଫአ෸ᛔۖๅ碝 Gemfile.lock • 舙羬ᕹჿ᪃犋ԧ Gemfile ጱ碝襑穩牧ڞಸᲙ • ࢩ種ྯ稞貉ۖ᮷ᥝ᯿碝薹 Gemfile + Gemfile.lock
  60. Molinillo ᓒဩ • Ӟӻ蝢አጱ狅ᩢ穩薹ᓒဩ • 玲ᛔ CocoaPods • ᬌ獈物狅ᩢ蹇կ҄狅ᩢᲁਧࢶ •

    ᬌڊ物狅ᩢ薹ࢶ
  61. 禊盢ು虡 • search_for(dependency) አ๶矾ᔱჿ᪃ᕳਧ狅ᩢጱ狅ᩢᥢ໒ • dependencies_for(specification) አ๶蜴ࢧᕳਧᥢ໒ጱ狅ᩢ • requirement_satisfied_by?(requirement, activated,

    spec) ࣁ୮ 獮ጱ狅ᩢࢶ activated Ӿᦇᓒ requirement ฎ玽胼ᤩ spec ჿ᪃ • sort_dependencies(dependencies, activated, conflicts) ԅ൉ ṛ௔胼牧ೲ“਻ฃ薹”ጱᶲଧ矎ଧ dependencies ؃ᦡਂࣁӞӻ“狅ᩢᥢ໒൉׀ᘏ”牧ਙ贶ሿইӥොဩ
  62. Molinillo ᓒဩጱ௏᪠ च๜௏మ——ࢧშဩ

  63. ຾ ᇫாᦡᦇ - ୮獮ጱ襑穩ጱݷਁ - ୮獮੢๚ჿ᪃ጱ襑穩褸ݳ - ୮獮蟂獤薹牧ܨ૪筕ၚጱ狅ᩢࢶ - ୮獮ጱ襑穩

    - ୮獮ጱ襑穩ጱݢᤈ薹褸 - 鉟趞窼ଶ - ٫统褸
  64. 狅ᩢா ܨӞञ襑穩޾Ӟञݢᤈ薹 ݢᤈ薹ா ܨӞञ襑穩޾Ӟӻݢᤈ薹 ຾

  65. Ԇ盌辘 ݝᥝ୮獮ᇫா鉕磪୮獮੢๚ჿ ᪃ጱ襑穩疰ᖀᖅ盌辘 ڡত狅ᩢா

  66. ੤ᦶ碝ጱݢᤈ薹 ڡত狅ᩢா ݢᤈ薹ா … 狅ᩢா ڡত狅ᩢா … 狅ᩢா 蟂獤薹ࢶӾฎ玽૪珀ᧆ薹牫ฎ玽ჿ᪃粚๜ᥝ穩牫
 ฎ玽ჿ᪃

    Gemfile.lock牫 ੤ᦶ筕ၚᧆݢᤈ薹
  67. ੤ᦶ碝ጱݢᤈ薹 ڡত狅ᩢா ݢᤈ薹ா … 狅ᩢா ڡত狅ᩢா … 狅ᩢா 舙०ᨳ牧ᦕ趟٫统牧ࢧშ

  68. ຾绚෫薹 ݱᐿࢧშ ڡত狅ᩢா … ୮獮ᇫா

  69. Ԇ盌辘 ڡত狅ᩢா … ୮獮ᇫா ڡত狅ᩢா … 薹ா
 ෫ๅग़襑穩 ୮獮蟂獤薹ܨ磧ᕣ薹 玲૪筕ၚጱ狅ᩢࢶ蜴ࢧ

  70. Molinillo ᓒဩጱ෸ᳵ瓰ᄖଶ • ᇫா绚ᳵጱय़ੜ 犔犥 ᇫா᫨ᑏጱᩇአ • ᇫா绚ᳵጱय़ੜ玲豙ԭ物狅ᩢ޾ৼ狅ᩢጱ踞ᰁ(m)牧 ݢ鉝ጱ粚๜ጱ磧य़踞ᰁ(n)牧n^m •

    O(n^m) • 贶ᴬኼ犭牧ଃ磪獮ᗝᶼၥ獶ຏ
  71. 盥綡 • ྯ稞貉ۖጱ෸狡ಗᤈ Molinillo ᓒဩ፥ጱ஠ᥝހ牫 • Gemfile + Gemfile.lock ጱݶྍ௔፥ጱ盄᯿ᥝހ牫

    • ᇚᇗྯ稞貉ۖ Ruby 纷ଧጱ硳ሲ牧绗ᒌഘ๶ԧՋԍ牫 • Gemfile.lock ጱᦡᦇฎ஠ᶳጱހ牫
  72. ᥝ犋൉ӻ Issue / PR牫

  73. 犡ଙ 5์26෭
 磪Ո൉鉑ԧ https://github.com/bundler/bundler/pull/4618

  74. None
  75. – Jason Frey “You know, you really shouldn't be resolving

    if you have a lockfile...”
  76. – Joe Rafaniello “Properly detect path spec changes to avoid

    needless re-resolve”
  77. If there were no changes, just use the resolution from

    Gemfile.lock.
  78. None
  79. None
  80. ੒穉 Rails ٖ蟂᧣አ 犌 ፗ矑᧣አ
 ௔胼ഖ聻磪ಅ犋ݶ

  81. None
  82. None
  83. ܻࢩ • bundler/setup ԏݸ牧य़ᰁጱ辘हݒᰁᤩ狕硬ҁই BUNDLE_GEMFILE牏RUBYLIB牏RUBYOPT牏 BUNDLE_BIN_PATH 缛҂ • ৼᬰ纷ᤩ貉ۖ෸ᖀ瞚ԧᆿᬰ纷ጱ辘हݒᰁҁই BUNDLE_GEMFILE牧ܨ

    Gemfile ጱ֖ᗝ҂ • ࢩ種୮ৼᬰ纷ᤩ貉ۖ෸牧ᆿᬰ纷ጱ Gemfile 蚏֢አ牧 ৼᬰ纷ጱ Gemfile ᤩ஺ኼ
  84. 薹豙ො礯物 Bundler.with_clean_env

  85. None
  86. Clean environment variables when running git hooks https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/ 6344

  87. None
  88. None
  89. 玱௏ • ஠ᶳ RUBYOPT=-rbundler/setup ހ牫 • bundler/setup ፥ጱ磪஠ᥝฎփ礕௔ጱހ牫

  90. 硽ᦒ • 犋ᥝ蝈מ๦শ牧ྯ稞᯿碝 resolve ଚ犋ฎกฬጱᦡᦇ • 犋੒ጱ瑿ො疰ᥝ玄碁᧔ڊ๶牧疰猟 Jason Frey ᮎ໏

    • ྯӻՈ᮷磪ݢ胼ݎሿଚ狕瓰 bug牧鉖ฎ୏რጱঅ賳
  91. 硽ᦒ • ൉Իᤑӟԏ獮ض፡Ӟӥฎ玽磪Ո൉Ի鉑牧౲ҁๅٍݢ 砺֢瑿҂ض礚፡磧碝୏ݎ獤ඪฎ玽Ֆ磪ᳯ᷌ • ࣙ瞱܋ᕆ gem ک磧碝粚๜ҁ bundler 1.13

    vs 1.12҂ • 犭玕অ Bundler牧Ruby ጱ貉ۖ෸ᳵݢ犥盠܈狝牦
  92. ᨀᨀ

  93. https://github.com/pmq20