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

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

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

Minqi Pan

September 24, 2016
Tweet

More Decks by Minqi Pan

Other Decks in Programming

Transcript

  1. 辘हݒᰁ

    ԅ֜胼ᦏ Ruby 盠܈狝
    笳碭ቡ

    View Slide

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

    View Slide

  3. View Slide

  4. View Slide

  5. View Slide

  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

    View Slide

  7. GitLab 耬ᵅ #15452
    https://gitlab.com/gitlab-org/gitlab-ce/issues/15452

    View Slide

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

    system(…update…)
    system(…post-receive…)

    View Slide

  9. Kernel#system

    View Slide

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

    View Slide

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

    View Slide

  12. 簁ᘒ unsetenv_others ݢ盵瓰蝧ଶ

    View Slide

  13. ٌਙᥡ疗ᕮຎ
    • “./update” ஠ᶳԅ Ruby 纷ଧ牧覍 Ruby 犋瓰ሿ
    • “./update” ݢ覍ଉᓌܔ牧 Hello World ܨݢ瓰ሿ

    View Slide

  14. [demo]

    View Slide

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

    View Slide

  16. gitlab-ce: MR-3939
    https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3939

    View Slide

  17. – Yorick Peterse
    “I'm a bit confused, how does unsetting
    environment variables make things run faster?”

    View Slide

  18. – Douwe Maan
    “The measurements don't lie, but I'm not quite
    sure why this works either. Can you elaborate?”

    View Slide

  19. चᏐᎣᦩ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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:

    View Slide

  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

    View Slide

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

    View Slide

  31. ᇨՈ΅͠獮Ͷ牦

    View Slide

  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

    View Slide

  33. RUBYOPT
    man ruby

    View Slide

  34. e.g.

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  41. bin/rails ᧣አԧ config/boot

    View Slide

  42. config/boot ᧣አԧ bundler/setup

    View Slide

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

    View Slide

  44. bundler/setup

    ฎՋԍ牫

    View Slide

  45. bundler/setup ฎӞӻ෈կ

    View Slide

  46. bundler/setup ጱֵአ࣋ว
    • bin/rails ᧣አԧ bundler/setup
    • bundle exec * ᧣አԧ bundler/setup
    • bundle show * ᧣አԧ bundler/setup
    • bundle bin-stubs ጱኞ౮ᇔ᮷᧣አԧ bundler/setup
    • ࢩ種 bundler/setup پԒฎ Ruby 貉ۖ鉑纷ጱຽ蟴

    View Slide

  47. bundler/setup ጱᦡᦇፓຽ
    • “make your code see just the dependencies that it
    should see and nothing else”
    • 矒ګঅ gem ପጱے᫹᪠趥矾ᔱᶲଧ
    • ᦏ纷ଧ௴অ胼୚አک Gemfile Ӿ瞲ਧጱ粚๜ጱପ
    • ᘒӬ獡ฎ Gemfile Ӿ๚瞲ਧጱ gem ᮷犋ݢᥠ

    View Slide

  48. Kernel#require
    • require ‘thing’
    • ইຎ ‘thing’ ૪ᕪے᫹鉑牧ಗᤈᕮ๳
    • 玽ڞ螁ܲ $LOAD_PATH ($:) ತک ‘thing’ ଚے᫹ԏ
    • 舙ತ犋کڞಲڊ LoadError

    View Slide

  49. rubygems/core_ext/
    kernel_require.rb
    • ᯿碝಑୏ Kernel ଚ remove_method ധԧ :require
    • ᯿碝ਧԎԧ Kernel#require
    • ᛔ Ruby 1.9 犥๶ RubyGems ฎٖᗝጱଚᛔۖ貉አ
    • ᛔ Ruby 1.9 犥๶鉖಍ฎ Kernel#require ጱ፥ྋᶎፓ

    View Slide

  50. rubygems/core_ext/
    kernel_require.rb
    • require ‘thing’
    • ইຎ ‘thing’ ૪ᕪے᫹鉑牧ಗᤈᕮ๳
    • 玽ڞ螁ܲ $LOAD_PATH ($:) ತک ‘thing’ ଚے᫹ԏ
    • 玽ڞ՗૪ਞᤰጱ gem Ӿ੔ತ ‘thing’ ଚ಩ᧆ gem ጱ
    ᪠趥ے獈 $LOAD_PATH ($:)
    • 舙ತ犋کڞಲڊ LoadError

    View Slide

  51. 牬demo]
    require pry, edit require

    View Slide

  52. bundler/setup ࣁ狶Ջԍ
    • ತکӞᕟ粬ਧ粚๜ጱ gem牧玲ڊ犢ժጱ gemspec
    • ಩ਙժጱ lib/ ፓ趟ጱᕷ੒᪠趥ے獈 $LOAD_PATH牧
    犥׎ Ruby ݢ犥 require ک粬ਧ粚๜ጱ gem
    • “unpatch”物݄ധ rubygems/core_ext/
    kernel_require.rb ጱ鉪ᬋ牧犥׎贶ሿ“獡ฎ Gemfile
    Ӿ๚瞲ਧጱ gem ᮷犋ݢᥠ”

    View Slide

  53. 牬demo]
    reverse_rubygems_kernel_mixin

    View Slide

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

    View Slide

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

    View Slide

  56. ෸ᳵ᮷݄ߺدԧ牫

    View Slide

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

    View Slide

  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 ᦡᦇ௏మጱ੒穉

    View Slide

  59. Gemfile 犌 Gemfile.lock 

    ݢ胼ڊሿ犋ݶྍ
    • ࣁ૪磪 Gemfile.lock ጱ眐٭ӥ牧አಁๅ碝ԧ Gemfile
    ᘒဌ磪᯿碝 bundle牧ڞ Gemfile.lock 鉑๗
    • 舙羬ᕹ૪磪胼ჿ᪃ Gemfile 碝襑穩ጱ gem牧ڞ貉ۖ
    ଫአ෸ᛔۖๅ碝 Gemfile.lock
    • 舙羬ᕹჿ᪃犋ԧ Gemfile ጱ碝襑穩牧ڞಸᲙ
    • ࢩ種ྯ稞貉ۖ᮷ᥝ᯿碝薹 Gemfile + Gemfile.lock

    View Slide

  60. Molinillo ᓒဩ
    • Ӟӻ蝢አጱ狅ᩢ穩薹ᓒဩ
    • 玲ᛔ CocoaPods
    • ᬌ獈物狅ᩢ蹇կ҄狅ᩢᲁਧࢶ
    • ᬌڊ物狅ᩢ薹ࢶ

    View Slide

  61. 禊盢ು虡
    • search_for(dependency) አ๶矾ᔱჿ᪃ᕳਧ狅ᩢጱ狅ᩢᥢ໒
    • dependencies_for(specification) አ๶蜴ࢧᕳਧᥢ໒ጱ狅ᩢ
    • requirement_satisfied_by?(requirement, activated, spec) ࣁ୮
    獮ጱ狅ᩢࢶ activated Ӿᦇᓒ requirement ฎ玽胼ᤩ spec ჿ᪃
    • sort_dependencies(dependencies, activated, conflicts) ԅ൉
    ṛ௔胼牧ೲ“਻ฃ薹”ጱᶲଧ矎ଧ dependencies
    ؃ᦡਂࣁӞӻ“狅ᩢᥢ໒൉׀ᘏ”牧ਙ贶ሿইӥොဩ

    View Slide

  62. Molinillo ᓒဩጱ௏᪠
    च๜௏మ——ࢧშဩ

    View Slide


  63. ᇫாᦡᦇ
    - ୮獮ጱ襑穩ጱݷਁ
    - ୮獮੢๚ჿ᪃ጱ襑穩褸ݳ
    - ୮獮蟂獤薹牧ܨ૪筕ၚጱ狅ᩢࢶ
    - ୮獮ጱ襑穩
    - ୮獮ጱ襑穩ጱݢᤈ薹褸
    - 鉟趞窼ଶ
    - ٫统褸

    View Slide

  64. 狅ᩢா
    ܨӞञ襑穩޾Ӟञݢᤈ薹
    ݢᤈ薹ா
    ܨӞञ襑穩޾Ӟӻݢᤈ薹

    View Slide

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

    View Slide

  66. ੤ᦶ碝ጱݢᤈ薹
    ڡত狅ᩢா
    ݢᤈ薹ா

    狅ᩢா
    ڡত狅ᩢா

    狅ᩢா
    蟂獤薹ࢶӾฎ玽૪珀ᧆ薹牫ฎ玽ჿ᪃粚๜ᥝ穩牫

    ฎ玽ჿ᪃ Gemfile.lock牫
    ੤ᦶ筕ၚᧆݢᤈ薹

    View Slide

  67. ੤ᦶ碝ጱݢᤈ薹
    ڡত狅ᩢா
    ݢᤈ薹ா

    狅ᩢா
    ڡত狅ᩢா

    狅ᩢா
    舙०ᨳ牧ᦕ趟٫统牧ࢧშ

    View Slide

  68. ຾绚෫薹
    ݱᐿࢧშ
    ڡত狅ᩢா

    ୮獮ᇫா

    View Slide

  69. Ԇ盌辘
    ڡত狅ᩢா

    ୮獮ᇫா
    ڡত狅ᩢா

    薹ா

    ෫ๅग़襑穩
    ୮獮蟂獤薹ܨ磧ᕣ薹
    玲૪筕ၚጱ狅ᩢࢶ蜴ࢧ

    View Slide

  70. Molinillo ᓒဩጱ෸ᳵ瓰ᄖଶ
    • ᇫா绚ᳵጱय़ੜ 犔犥 ᇫா᫨ᑏጱᩇአ
    • ᇫா绚ᳵጱय़ੜ玲豙ԭ物狅ᩢ޾ৼ狅ᩢጱ踞ᰁ(m)牧
    ݢ鉝ጱ粚๜ጱ磧य़踞ᰁ(n)牧n^m
    • O(n^m)
    • 贶ᴬኼ犭牧ଃ磪獮ᗝᶼၥ獶ຏ

    View Slide

  71. 盥綡
    • ྯ稞貉ۖጱ෸狡ಗᤈ Molinillo ᓒဩ፥ጱ஠ᥝހ牫
    • Gemfile + Gemfile.lock ጱݶྍ௔፥ጱ盄᯿ᥝހ牫
    • ᇚᇗྯ稞貉ۖ Ruby 纷ଧጱ硳ሲ牧绗ᒌഘ๶ԧՋԍ牫
    • Gemfile.lock ጱᦡᦇฎ஠ᶳጱހ牫

    View Slide

  72. ᥝ犋൉ӻ Issue / PR牫

    View Slide

  73. 犡ଙ 5์26෭

    磪Ո൉鉑ԧ
    https://github.com/bundler/bundler/pull/4618

    View Slide

  74. View Slide

  75. – Jason Frey
    “You know, you really shouldn't be resolving if
    you have a lockfile...”

    View Slide

  76. – Joe Rafaniello
    “Properly detect path spec changes to avoid
    needless re-resolve”

    View Slide

  77. If there were no changes,
    just use the resolution
    from Gemfile.lock.

    View Slide

  78. View Slide

  79. View Slide

  80. ੒穉 Rails ٖ蟂᧣አ 犌 ፗ矑᧣አ

    ௔胼ഖ聻磪ಅ犋ݶ

    View Slide

  81. View Slide

  82. View Slide

  83. ܻࢩ
    • bundler/setup ԏݸ牧य़ᰁጱ辘हݒᰁᤩ狕硬ҁই
    BUNDLE_GEMFILE牏RUBYLIB牏RUBYOPT牏
    BUNDLE_BIN_PATH 缛҂
    • ৼᬰ纷ᤩ貉ۖ෸ᖀ瞚ԧᆿᬰ纷ጱ辘हݒᰁҁই
    BUNDLE_GEMFILE牧ܨ Gemfile ጱ֖ᗝ҂
    • ࢩ種୮ৼᬰ纷ᤩ貉ۖ෸牧ᆿᬰ纷ጱ Gemfile 蚏֢አ牧
    ৼᬰ纷ጱ Gemfile ᤩ஺ኼ

    View Slide

  84. 薹豙ො礯物
    Bundler.with_clean_env

    View Slide

  85. View Slide

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

    View Slide

  87. View Slide

  88. View Slide

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

    View Slide

  90. 硽ᦒ
    • 犋ᥝ蝈מ๦শ牧ྯ稞᯿碝 resolve ଚ犋ฎกฬጱᦡᦇ
    • 犋੒ጱ瑿ො疰ᥝ玄碁᧔ڊ๶牧疰猟 Jason Frey ᮎ໏
    • ྯӻՈ᮷磪ݢ胼ݎሿଚ狕瓰 bug牧鉖ฎ୏რጱঅ賳

    View Slide

  91. 硽ᦒ
    • ൉Իᤑӟԏ獮ض፡Ӟӥฎ玽磪Ո൉Ի鉑牧౲ҁๅٍݢ
    砺֢瑿҂ض礚፡磧碝୏ݎ獤ඪฎ玽Ֆ磪ᳯ᷌
    • ࣙ瞱܋ᕆ gem ک磧碝粚๜ҁ bundler 1.13 vs 1.12҂
    • 犭玕অ Bundler牧Ruby ጱ貉ۖ෸ᳵݢ犥盠܈狝牦

    View Slide

  92. ᨀᨀ

    View Slide

  93. https://github.com/pmq20

    View Slide