【Ruby 2.6新機能紹介】
本番環境で使える
実行コード記録機能
遠藤侑介
Cookpad TechConf 2019 LT
遠藤侑介 (@mametter)
• Rubyコミッタ
• プログラミング言語Ruby開発メンバ
• テストを中心にいろいろやってます
• フルタイムRubyコミッタ
• Ruby開発がクックパッドでの業務
w/ 笹田耕一
• Ruby3の静的解析が主ミッション
Ruby 2.6 リリース
• 終端なしRange
• unicode 定数名
• cause 表示
• refinement拡張
• ブロック to_h
• Enum#chain
• #Arithmetic
Sequence
• Kernel#then
• Proc 合成
• exception 引数
• Array#union と
#difference
• Array#filter
• Binding#
source_locatoin
• Dir#each_child
• Exception#full_
message拡張
• Hash#merge拡張
• Random.bytes
• ブロック
String#split
• Unicode 11.0.0
• RubyVM::AST
• RubyVM.resolve_
feature_path
• TracePoint拡張
• Bundler 同梱
• oneshot coverage
• FileUtils#cp_lr
• Matrixの破壊的更新
•rescue なし else
•フリップフロップ
•File.read("|...")
•String#crypt
•Object#=~
•Procレベルの$SAFE
•MJIT
•Proc高速化
•VM生成系の一新
•スレッドキャッシュ
•タイマースレッド削除
•Fiber の実装向上
•Transient Heap
新機能 廃止・非推奨
性能改善
• 終端なしRange
• unicode 定数名
• cause 表示
• refinement拡張
• ブロック to_h
• Enum#chain
• #Arithmetic
Sequence
• Kernel#then
• Proc 合成
• exception 引数
• Array#union と
#difference
• Array#filter
• Binding#
source_locatoin
• Dir#each_child
• Exception#full_
message拡張
• Hash#merge拡張
• Random.bytes
• ブロック
String#split
• Unicode 11.0.0
• RubyVM::AST
• RubyVM.resolve_
feature_path
• TracePoint拡張
• Bundler 同梱
• oneshot coverage
• FileUtils#cp_lr
• Matrixの破壊的更新
•rescue なし else
•フリップフロップ
•File.read("|...")
•String#crypt
•Object#=~
•Procレベルの$SAFE
•MJIT
•Proc高速化
•VM生成系の一新
•スレッドキャッシュ
•タイマースレッド削除
•Fiber の実装向上
•Transient Heap
新機能 廃止・非推奨
性能改善
Ruby 2.6 リリース
クックパッドのフルタイムコミッタが主導、または深く関わった機能
• 終端なしRange
• unicode 定数名
• cause 表示
• refinement拡張
• ブロック to_h
• Enum#chain
• #Arithmetic
Sequence
• Kernel#then
• Proc 合成
• exception 引数
• Array#union と
#difference
• Array#filter
• Binding#
source_locatoin
• Dir#each_child
• Exception#full_
message拡張
• Hash#merge拡張
• Random.bytes
• ブロック
String#split
• Unicode 11.0.0
• Ruby::AST
• RubyVM.resolve_
feature_path
• TracePoint拡張
• Bundler 同梱
• oneshot coverage
• FileUtils#cp_lr
• Matrixの破壊的更新
•rescue なし else
•フリップフロップ
•File.read("|...")
•String#crypt
•Object#=~
•Procレベルの$SAFE
•MJIT
•Proc高速化
•VM生成系の一新
•スレッドキャッシュ
•タイマースレッド削除
•Fiber の実装向上
•Transient Heap
新機能 廃止・非推奨
性能改善
詳しくは『クックパッド開発者ブログ –
プロと読み解く Ruby 2.6 NEWS ファイル』
Ruby 2.6 リリース
クックパッドのフルタイムコミッタが主導、または深く関わった機能
• 終端なしRange
• unicode 定数名
• cause 表示
• refinement拡張
• ブロック to_h
• Enum#chain
• #Arithmetic
Sequence
• Kernel#then
• Proc 合成
• exception 引数
• Array#union と
#difference
• Array#filter
• Binding#
source_locatoin
• Dir#each_child
• Exception#full_
message拡張
• Hash#merge拡張
• Random.bytes
• ブロック
String#split
• Unicode 11.0.0
• Ruby::AST
• RubyVM.resolve_
feature_path
• TracePoint拡張
• Bundler 同梱
• oneshot coverage
• FileUtils#cp_lr
• Matrixの破壊的更新
•rescue なし else
•フリップフロップ
•File.read("|...")
•String#crypt
•Object#=~
•Procレベルの$SAFE
•MJIT
•Proc高速化
•VM生成系の一新
•スレッドキャッシュ
•タイマースレッド削除
•Fiber の実装向上
•Transient Heap
新機能 廃止・非推奨
性能改善
今日のテーマ
詳しくは『クックパッド開発者ブログ –
プロと読み解く Ruby 2.6 NEWS ファイル』
Ruby 2.6 リリース
クックパッドのフルタイムコミッタが主導、または深く関わった機能
背景:お台場プロジェクト
• クックパッドの中核サービスの
アーキテクチャ改善プロジェクト
• APIサーバーのアーキテクチャ改善
• 不要なサービスの廃止
• デッドコードの自動検出と削除
• ストレージ数の削減
• 特殊な実行環境・開発環境の廃止
背景:お台場プロジェクト
• クックパッドの中核サービスの
アーキテクチャ改善プロジェクト
• APIサーバーのアーキテクチャ改善
• 不要なサービスの廃止
• デッドコードの自動検出と削除
• ストレージ数の削減
• 特殊な実行環境・開発環境の廃止
詳しくは『クックパッド開発者ブログ –
クックパッド基幹システムのmicroservices化戦略
〜お台場プロジェクト1年半の軌跡〜』
背景:お台場プロジェクト
• クックパッドの中核サービスの
アーキテクチャ改善プロジェクト
• APIサーバーのアーキテクチャ改善
• 不要なサービスの廃止
• デッドコードの自動検出と削除
• ストレージ数の削減
• 特殊な実行環境・開発環境の廃止
詳しくは『クックパッド開発者ブログ –
クックパッド基幹システムのmicroservices化戦略
〜お台場プロジェクト1年半の軌跡〜』
デッドコードの削除
• 実行されないコードを見つける
• 動的言語のRubyでは意外に大変
• クックパッドでは、rubyインタプリタに
パッチを当てて実行を記録してた(!)
デッドコードの削除
• 実行されないコードを見つける
• 動的言語のRubyでは意外に大変
• クックパッドでは、rubyインタプリタに
パッチを当てて実行を記録してた(!)
詳しくは『クックパッド開発者ブログ –
Ruby の lazy loading の仕組みを利用して
未使用の gem を探す』
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
=> {"program.rb"=>{
:oneshot_lines=>
[1, 2]}}
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
=> {"program.rb"=>{
:oneshot_lines=>
[1, 2]}}
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
=> {"program.rb"=>{
:oneshot_lines=>
[1, 2]}}
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
1・2行目が実行された
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
=> {"program.rb"=>{
:oneshot_lines=>
[1, 2]}}
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
1・2行目が実行された
➔4行目は実行されなかった
(3・5行目は無意味)
1: if 42 > 0
2: puts "used"
3: else
4: puts "unused"
5: end
Ruby 2.6新機能:
oneshot coverage
• 実行された行番号を記録する機能
require "coverage"
Coverage.start(
oneshot_lines: true)
load "program.rb"
p Coverage.result
=> {"program.rb"=>{
:oneshot_lines=>
[1, 2]}}
1・2行目が実行された
➔4行目は実行されなかった
(3・5行目は無意味)
詳しくは『クックパッド開発者ブログ --
Ruby 2.6 新機能:本番環境での利用を目指した
コードカバレッジ計測機能』
実装上の工夫
• 実行記録フックのフラグが
バイトコードについている
• フックが1回走ったらフラグを消す
• 2回め以降はゼロオーバーヘッド
• フラグ参照も工夫されている
• 簡潔データ構造の利用など
詳しくは『Ruby 2.5 の改善を自慢したい』
詳しくは『簡潔ビットベクトルでRubyをlog N倍速くした』
本当に本番環境でも使える?
• 鋭意作業中
詳しくは RubyKaigi の次の発表で……
Sangyong Sim
"Cleaning up a huge ruby application"
まとめ
• クックパッドでの実課題から
Rubyに実行された行番号を
調べる新機能を入れました
• 『クックパッド開発者ブログ』は情報満載
https://techlife.cookpad.com/

本番環境で使える実行コード記録機能

  • 1.
  • 2.
    遠藤侑介 (@mametter) • Rubyコミッタ •プログラミング言語Ruby開発メンバ • テストを中心にいろいろやってます • フルタイムRubyコミッタ • Ruby開発がクックパッドでの業務 w/ 笹田耕一 • Ruby3の静的解析が主ミッション
  • 3.
    Ruby 2.6 リリース •終端なしRange • unicode 定数名 • cause 表示 • refinement拡張 • ブロック to_h • Enum#chain • #Arithmetic Sequence • Kernel#then • Proc 合成 • exception 引数 • Array#union と #difference • Array#filter • Binding# source_locatoin • Dir#each_child • Exception#full_ message拡張 • Hash#merge拡張 • Random.bytes • ブロック String#split • Unicode 11.0.0 • RubyVM::AST • RubyVM.resolve_ feature_path • TracePoint拡張 • Bundler 同梱 • oneshot coverage • FileUtils#cp_lr • Matrixの破壊的更新 •rescue なし else •フリップフロップ •File.read("|...") •String#crypt •Object#=~ •Procレベルの$SAFE •MJIT •Proc高速化 •VM生成系の一新 •スレッドキャッシュ •タイマースレッド削除 •Fiber の実装向上 •Transient Heap 新機能 廃止・非推奨 性能改善
  • 4.
    • 終端なしRange • unicode定数名 • cause 表示 • refinement拡張 • ブロック to_h • Enum#chain • #Arithmetic Sequence • Kernel#then • Proc 合成 • exception 引数 • Array#union と #difference • Array#filter • Binding# source_locatoin • Dir#each_child • Exception#full_ message拡張 • Hash#merge拡張 • Random.bytes • ブロック String#split • Unicode 11.0.0 • RubyVM::AST • RubyVM.resolve_ feature_path • TracePoint拡張 • Bundler 同梱 • oneshot coverage • FileUtils#cp_lr • Matrixの破壊的更新 •rescue なし else •フリップフロップ •File.read("|...") •String#crypt •Object#=~ •Procレベルの$SAFE •MJIT •Proc高速化 •VM生成系の一新 •スレッドキャッシュ •タイマースレッド削除 •Fiber の実装向上 •Transient Heap 新機能 廃止・非推奨 性能改善 Ruby 2.6 リリース クックパッドのフルタイムコミッタが主導、または深く関わった機能
  • 5.
    • 終端なしRange • unicode定数名 • cause 表示 • refinement拡張 • ブロック to_h • Enum#chain • #Arithmetic Sequence • Kernel#then • Proc 合成 • exception 引数 • Array#union と #difference • Array#filter • Binding# source_locatoin • Dir#each_child • Exception#full_ message拡張 • Hash#merge拡張 • Random.bytes • ブロック String#split • Unicode 11.0.0 • Ruby::AST • RubyVM.resolve_ feature_path • TracePoint拡張 • Bundler 同梱 • oneshot coverage • FileUtils#cp_lr • Matrixの破壊的更新 •rescue なし else •フリップフロップ •File.read("|...") •String#crypt •Object#=~ •Procレベルの$SAFE •MJIT •Proc高速化 •VM生成系の一新 •スレッドキャッシュ •タイマースレッド削除 •Fiber の実装向上 •Transient Heap 新機能 廃止・非推奨 性能改善 詳しくは『クックパッド開発者ブログ – プロと読み解く Ruby 2.6 NEWS ファイル』 Ruby 2.6 リリース クックパッドのフルタイムコミッタが主導、または深く関わった機能
  • 6.
    • 終端なしRange • unicode定数名 • cause 表示 • refinement拡張 • ブロック to_h • Enum#chain • #Arithmetic Sequence • Kernel#then • Proc 合成 • exception 引数 • Array#union と #difference • Array#filter • Binding# source_locatoin • Dir#each_child • Exception#full_ message拡張 • Hash#merge拡張 • Random.bytes • ブロック String#split • Unicode 11.0.0 • Ruby::AST • RubyVM.resolve_ feature_path • TracePoint拡張 • Bundler 同梱 • oneshot coverage • FileUtils#cp_lr • Matrixの破壊的更新 •rescue なし else •フリップフロップ •File.read("|...") •String#crypt •Object#=~ •Procレベルの$SAFE •MJIT •Proc高速化 •VM生成系の一新 •スレッドキャッシュ •タイマースレッド削除 •Fiber の実装向上 •Transient Heap 新機能 廃止・非推奨 性能改善 今日のテーマ 詳しくは『クックパッド開発者ブログ – プロと読み解く Ruby 2.6 NEWS ファイル』 Ruby 2.6 リリース クックパッドのフルタイムコミッタが主導、または深く関わった機能
  • 7.
    背景:お台場プロジェクト • クックパッドの中核サービスの アーキテクチャ改善プロジェクト • APIサーバーのアーキテクチャ改善 •不要なサービスの廃止 • デッドコードの自動検出と削除 • ストレージ数の削減 • 特殊な実行環境・開発環境の廃止
  • 8.
    背景:お台場プロジェクト • クックパッドの中核サービスの アーキテクチャ改善プロジェクト • APIサーバーのアーキテクチャ改善 •不要なサービスの廃止 • デッドコードの自動検出と削除 • ストレージ数の削減 • 特殊な実行環境・開発環境の廃止 詳しくは『クックパッド開発者ブログ – クックパッド基幹システムのmicroservices化戦略 〜お台場プロジェクト1年半の軌跡〜』
  • 9.
    背景:お台場プロジェクト • クックパッドの中核サービスの アーキテクチャ改善プロジェクト • APIサーバーのアーキテクチャ改善 •不要なサービスの廃止 • デッドコードの自動検出と削除 • ストレージ数の削減 • 特殊な実行環境・開発環境の廃止 詳しくは『クックパッド開発者ブログ – クックパッド基幹システムのmicroservices化戦略 〜お台場プロジェクト1年半の軌跡〜』
  • 10.
    デッドコードの削除 • 実行されないコードを見つける • 動的言語のRubyでは意外に大変 •クックパッドでは、rubyインタプリタに パッチを当てて実行を記録してた(!)
  • 11.
    デッドコードの削除 • 実行されないコードを見つける • 動的言語のRubyでは意外に大変 •クックパッドでは、rubyインタプリタに パッチを当てて実行を記録してた(!) 詳しくは『クックパッド開発者ブログ – Ruby の lazy loading の仕組みを利用して 未使用の gem を探す』
  • 12.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end
  • 13.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end
  • 14.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result => {"program.rb"=>{ :oneshot_lines=> [1, 2]}} 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end
  • 15.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result => {"program.rb"=>{ :oneshot_lines=> [1, 2]}} 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end
  • 16.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result => {"program.rb"=>{ :oneshot_lines=> [1, 2]}} 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end 1・2行目が実行された
  • 17.
    Ruby 2.6新機能: oneshot coverage •実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result => {"program.rb"=>{ :oneshot_lines=> [1, 2]}} 1: if 42 > 0 2: puts "used" 3: else 4: puts "unused" 5: end 1・2行目が実行された ➔4行目は実行されなかった (3・5行目は無意味)
  • 18.
    1: if 42> 0 2: puts "used" 3: else 4: puts "unused" 5: end Ruby 2.6新機能: oneshot coverage • 実行された行番号を記録する機能 require "coverage" Coverage.start( oneshot_lines: true) load "program.rb" p Coverage.result => {"program.rb"=>{ :oneshot_lines=> [1, 2]}} 1・2行目が実行された ➔4行目は実行されなかった (3・5行目は無意味) 詳しくは『クックパッド開発者ブログ -- Ruby 2.6 新機能:本番環境での利用を目指した コードカバレッジ計測機能』
  • 19.
    実装上の工夫 • 実行記録フックのフラグが バイトコードについている • フックが1回走ったらフラグを消す •2回め以降はゼロオーバーヘッド • フラグ参照も工夫されている • 簡潔データ構造の利用など 詳しくは『Ruby 2.5 の改善を自慢したい』 詳しくは『簡潔ビットベクトルでRubyをlog N倍速くした』
  • 20.
    本当に本番環境でも使える? • 鋭意作業中 詳しくは RubyKaigiの次の発表で…… Sangyong Sim "Cleaning up a huge ruby application"
  • 21.