SlideShare une entreprise Scribd logo
1  sur  11
Télécharger pour lire hors ligne
z
細かいrubyの
話?(仮)
@taru 樽家昌也
z
最近読み始めた本
▪ なんかRubyと関係ある人が訳
者にはいっているらしいよ
▪ 追記型データ構造面白いよ!
▪ 最初は二分木を用いたソートと
かから・・・
z
準備フェーズがあると
のような、関数内関数定義したくなりますよね・・・
ソートといえば
def exist?(a,tree)
return false if tree.empty?
left,node,right=tree
if (node<a) then return exist?(a,left)
if (node>a) then return exist?(a,right)
return node==a
単純には
みたいな再帰構造だが。。。。
func x = f x init_state
where f a st = hogehogehoge…
z
Rubyで書こうとすると
def func(a)
def sub(a,st)
hogehogehoge…
end
sub(a,init_state)
end
×
関数定義はスコープに閉じてくれない
def func(a)
sub = proc { …}
sub.call(a,init_state)
end
procを使うとかけるが….
z
遅い!
def func_p(d,n)
pr = proc{|d,n|
next hook if n==0
pr.call([d,d],n-1)
}
pr.call(d,n)
end
def func_m(d,n)
def func_m_sub(d,n)
return hook if n==0
func_m_sub([d,d],n-1)
end
func_m_sub(d,n)
end
N=2000
Benchmark.ips do |x|
x.report("func_p") { func_p(1,N) }
x.report("func_m") { func_m(1,N) }
x.compare!
end
Warming up --------------------------------------
func_p 86.000 i/100ms
func_m 391.000 i/100ms
Calculating -------------------------------------
func_p 1.063k (±59.1%) i/s - 1.032k in 6.066881s
func_m 3.987k (± 3.6%) i/s - 19.941k in 5.007711s
Comparison:
func_m: 3986.7 i/s
func_p: 1062.7 i/s - 3.75x slower
ここだけの話、
少し緩和できる方法があります。
z
そこで、細かい話
def proc_call (*args)
yield *args
end
def func_py(d,n)
pr = proc{|d,n|
next hook if n==0
proc_call([d,d],n-1,&pr)
}
proc_call (d,n,&pr)
end
Warming up --------------------------------------
func_p 86.000 i/100ms
func_py 143.000 i/100ms
func_m 391.000 i/100ms
Calculating -------------------------------------
func_p 1.063k (±59.1%) i/s - 1.032k in 6.066881s
func_py 1.435k (± 2.6%) i/s - 7.293k in 5.083872s
func_m 3.987k (± 3.6%) i/s - 19.941k in 5.007711s
Comparison:
func_m: 3986.7 i/s
func_py: 1435.5 i/s - 2.78x slower
func_p: 1062.7 i/s - 3.75x slower
1.35x faster!!
結論: (今のRubyでrubyで書いた)
procはcallせずにyieldしろ!
(特に再帰するなら)
z
第一部完 ご清聴ありがとうございました
procはcallせずにyieldしろ!
z
ここから裏話 資料が適当になります
なんでProc#callが遅いのか-- C level backtrace information -------------------------------------------
/usr/ruby/2.3.1/bin/ruby(rb_vm_bugreport+0x51f) [0x7f7c6570178f] vm_dump.c:688
/usr/ruby/2.3.1/bin/ruby(rb_bug_context+0xd0) [0x7f7c656dbe30] error.c:435
/usr/ruby/2.3.1/bin/ruby(sigsegv+0x3e) [0x7f7c655d5dae] signal.c:890
/lib/x86_64-linux-gnu/libpthread.so.0 [0x7f7c650b4330]
/usr/ruby/2.3.1/lib/ruby/2.3.0/x86_64-linux/fiddle.so(rb_fiddle_ptr_aset+0x130) [0x7f7c636699c0] pointer.c:587
/usr/ruby/2.3.1/bin/ruby(vm_call_cfunc+0xf6) [0x7f7c65657f76] vm_insnhelper.c:1638
/usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x15ec) [0x7f7c6565fd9c] insns.def:1893
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(ruby_exec_internal+0xc4) [0x7f7c6550c0e4] eval.c:245
/usr/ruby/2.3.1/bin/ruby(ruby_run_node+0x2d) [0x7f7c6550fcad] eval.c:310
/usr/ruby/2.3.1/bin/ruby(main+0x4b) [0x7f7c6550bd4b] addr2line.c:179
-- Ruby level backtrace information ----------------------------------------
test.rb:73:in `<main>'
test.rb:15:in `func_p'
test.rb:13:in `block in func_p'
test.rb:13:in `block in func_p'
test.rb:13:in `block in func_p'
test.rb:13:in `block in func_p'
test.rb:13:in `block in func_p'
test.rb:12:in `block in func_p'
test.rb:70:in `hook'
test.rb:70:in `[]='
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971
/usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996
/usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650
call毎にCのマシンスタックが沢山積み重なる
z
細かい話その2
def callbug
require 'fiddle'
Fiddle::Pointer.new(4)[0]=0
end
Cのマシンスタックを簡単に取得する
たった一つじゃない簡単な方法
これで callbug を呼ぶだけ!
z
なんでyieldが速いのか
-- C level backtrace information -------------------------------------------
/usr/ruby/2.3.1/bin/ruby(rb_vm_bugreport+0x51f) [0x7f0977a0978f] vm_dump.c:688
/usr/ruby/2.3.1/bin/ruby(rb_bug_context+0xd0) [0x7f09779e3e30] error.c:435
/usr/ruby/2.3.1/bin/ruby(sigsegv+0x3e) [0x7f09778dddae] signal.c:890
/lib/x86_64-linux-gnu/libpthread.so.0 [0x7f09773bc330]
/usr/ruby/2.3.1/lib/ruby/2.3.0/x86_64-linux/fiddle.so(rb_fiddle_ptr_aset+0x130) [0x7f09759719c0] pointer.c:587
/usr/ruby/2.3.1/bin/ruby(vm_call_cfunc+0xf6) [0x7f097795ff76] vm_insnhelper.c:1638
/usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f097796dd43] vm_insnhelper.c:2172
/usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x15ec) [0x7f0977967d9c] insns.def:1893
/usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f097796c3d1] vm.c:1650
/usr/ruby/2.3.1/bin/ruby(ruby_exec_internal+0xc4) [0x7f09778140e4] eval.c:245
/usr/ruby/2.3.1/bin/ruby(ruby_run_node+0x2d) [0x7f0977817cad] eval.c:310
/usr/ruby/2.3.1/bin/ruby(main+0x4b) [0x7f0977813d4b] addr2line.c:179
-- Ruby level backtrace information ----------------------------------------
test.rb:74:in `<main>'
test.rb:34:in `func_py'
test.rb:26:in `sub'
test.rb:32:in `block in func_py'
test.rb:26:in `sub'
test.rb:32:in `block in func_py'
test.rb:26:in `sub'
test.rb:32:in `block in func_py'
test.rb:26:in `sub'
test.rb:32:in `block in func_py'
test.rb:26:in `sub'
test.rb:32:in `block in func_py'
test.rb:26:in `sub'
test.rb:31:in `block in func_py'
test.rb:70:in `hook'
test.rb:70:in `[]='
DEFINE_INSN
invokeblock
(CALL_INFO ci)
(...)
(VALUE val) // inc += 1 - ci->orig_argc;
{
struct rb_calling_info calling;
calling.argc = ci->orig_argc;
calling.block_handler = VM_BLOCK_HANDLER_NONE;
calling.recv = GET_SELF();
val = vm_invoke_block(th, GET_CFP(), &calling, ci);
if (val == Qundef) {
RESTORE_REGS();
NEXT_INSN();
}
頑張って最適化した人がいるから
ruby –dump=insn
すると、yieldはinvokeblockという
命令になっていることがわかる。
z
まとめ
def callbug
require 'fiddle'
Fiddle::Pointer.new(4)[0]=0
end
def proc_call (*args)
yield *args
end
ruby –dump=insn
Ruby3x3までにはなんとか・・・

Contenu connexe

Tendances

Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
Yandex
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
Moriyoshi Koizumi
 
ch3-pv1-memory-management
ch3-pv1-memory-managementch3-pv1-memory-management
ch3-pv1-memory-management
yushiang fu
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
timotheeg
 
Seeley yonik solr performance key innovations
Seeley yonik   solr performance key innovationsSeeley yonik   solr performance key innovations
Seeley yonik solr performance key innovations
Lucidworks (Archived)
 
C++totural file
C++totural fileC++totural file
C++totural file
halaisumit
 

Tendances (19)

Introduction to Kernel Programming
Introduction to Kernel ProgrammingIntroduction to Kernel Programming
Introduction to Kernel Programming
 
OOP in Rust
OOP in RustOOP in Rust
OOP in Rust
 
The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196The Ring programming language version 1.7 book - Part 83 of 196
The Ring programming language version 1.7 book - Part 83 of 196
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
Python 5-迴圈-while
Python 5-迴圈-whilePython 5-迴圈-while
Python 5-迴圈-while
 
Qt Rest Server
Qt Rest ServerQt Rest Server
Qt Rest Server
 
C++ tutorial
C++ tutorialC++ tutorial
C++ tutorial
 
ch3-pv1-memory-management
ch3-pv1-memory-managementch3-pv1-memory-management
ch3-pv1-memory-management
 
Txjs
TxjsTxjs
Txjs
 
JavaScript Patterns
JavaScript PatternsJavaScript Patterns
JavaScript Patterns
 
The mighty js_function
The mighty js_functionThe mighty js_function
The mighty js_function
 
Seeley yonik solr performance key innovations
Seeley yonik   solr performance key innovationsSeeley yonik   solr performance key innovations
Seeley yonik solr performance key innovations
 
Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1Cleanup and new optimizations in WPython 1.1
Cleanup and new optimizations in WPython 1.1
 
C++totural file
C++totural fileC++totural file
C++totural file
 
TraitとMoose::Role
TraitとMoose::RoleTraitとMoose::Role
TraitとMoose::Role
 
Objective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central DispatchObjective-C Blocks and Grand Central Dispatch
Objective-C Blocks and Grand Central Dispatch
 
Parsing JSON Really Quickly: Lessons Learned
Parsing JSON Really Quickly: Lessons LearnedParsing JSON Really Quickly: Lessons Learned
Parsing JSON Really Quickly: Lessons Learned
 
WebGL - 3D in your Browser
WebGL - 3D in your BrowserWebGL - 3D in your Browser
WebGL - 3D in your Browser
 

Similaire à 東急Ruby会議向け「rubyの細かい話」

Im trying to run make qemu-nox In a putty terminal but it.pdf
Im trying to run  make qemu-nox  In a putty terminal but it.pdfIm trying to run  make qemu-nox  In a putty terminal but it.pdf
Im trying to run make qemu-nox In a putty terminal but it.pdf
maheshkumar12354
 

Similaire à 東急Ruby会議向け「rubyの細かい話」 (20)

[CCC-28c3] Post Memory Corruption Memory Analysis
[CCC-28c3] Post Memory Corruption Memory Analysis[CCC-28c3] Post Memory Corruption Memory Analysis
[CCC-28c3] Post Memory Corruption Memory Analysis
 
Clojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVMClojure: Practical functional approach on JVM
Clojure: Practical functional approach on JVM
 
C c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdoC c++-meetup-1nov2017-autofdo
C c++-meetup-1nov2017-autofdo
 
PHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP LimogesPHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP Limoges
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
[Ruxcon 2011] Post Memory Corruption Memory Analysis
[Ruxcon 2011] Post Memory Corruption Memory Analysis[Ruxcon 2011] Post Memory Corruption Memory Analysis
[Ruxcon 2011] Post Memory Corruption Memory Analysis
 
Tokyo APAC Groundbreakers tour - The Complete Java Developer
Tokyo APAC Groundbreakers tour - The Complete Java DeveloperTokyo APAC Groundbreakers tour - The Complete Java Developer
Tokyo APAC Groundbreakers tour - The Complete Java Developer
 
Naughty And Nice Bash Features
Naughty And Nice Bash FeaturesNaughty And Nice Bash Features
Naughty And Nice Bash Features
 
MP in Clojure
MP in ClojureMP in Clojure
MP in Clojure
 
[HITB Malaysia 2011] Exploit Automation
[HITB Malaysia 2011] Exploit Automation[HITB Malaysia 2011] Exploit Automation
[HITB Malaysia 2011] Exploit Automation
 
HaskellとDebianの辛くて甘い関係
HaskellとDebianの辛くて甘い関係HaskellとDebianの辛くて甘い関係
HaskellとDebianの辛くて甘い関係
 
Clojure concurrency overview
Clojure concurrency overviewClojure concurrency overview
Clojure concurrency overview
 
JRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVMJRuby 9000 - Optimizing Above the JVM
JRuby 9000 - Optimizing Above the JVM
 
The promise of asynchronous PHP
The promise of asynchronous PHPThe promise of asynchronous PHP
The promise of asynchronous PHP
 
JSDC 2014 - functional java script, why or why not
JSDC 2014 - functional java script, why or why notJSDC 2014 - functional java script, why or why not
JSDC 2014 - functional java script, why or why not
 
[Kiwicon 2011] Post Memory Corruption Memory Analysis
[Kiwicon 2011] Post Memory Corruption Memory Analysis[Kiwicon 2011] Post Memory Corruption Memory Analysis
[Kiwicon 2011] Post Memory Corruption Memory Analysis
 
Im trying to run make qemu-nox In a putty terminal but it.pdf
Im trying to run  make qemu-nox  In a putty terminal but it.pdfIm trying to run  make qemu-nox  In a putty terminal but it.pdf
Im trying to run make qemu-nox In a putty terminal but it.pdf
 
Performance Profiling in Rust
Performance Profiling in RustPerformance Profiling in Rust
Performance Profiling in Rust
 
Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)Being functional in PHP (PHPDay Italy 2016)
Being functional in PHP (PHPDay Italy 2016)
 
Php engine
Php enginePhp engine
Php engine
 

Dernier

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Dernier (20)

08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 

東急Ruby会議向け「rubyの細かい話」

  • 3. z 準備フェーズがあると のような、関数内関数定義したくなりますよね・・・ ソートといえば def exist?(a,tree) return false if tree.empty? left,node,right=tree if (node<a) then return exist?(a,left) if (node>a) then return exist?(a,right) return node==a 単純には みたいな再帰構造だが。。。。 func x = f x init_state where f a st = hogehogehoge…
  • 5. z 遅い! def func_p(d,n) pr = proc{|d,n| next hook if n==0 pr.call([d,d],n-1) } pr.call(d,n) end def func_m(d,n) def func_m_sub(d,n) return hook if n==0 func_m_sub([d,d],n-1) end func_m_sub(d,n) end N=2000 Benchmark.ips do |x| x.report("func_p") { func_p(1,N) } x.report("func_m") { func_m(1,N) } x.compare! end Warming up -------------------------------------- func_p 86.000 i/100ms func_m 391.000 i/100ms Calculating ------------------------------------- func_p 1.063k (±59.1%) i/s - 1.032k in 6.066881s func_m 3.987k (± 3.6%) i/s - 19.941k in 5.007711s Comparison: func_m: 3986.7 i/s func_p: 1062.7 i/s - 3.75x slower ここだけの話、 少し緩和できる方法があります。
  • 6. z そこで、細かい話 def proc_call (*args) yield *args end def func_py(d,n) pr = proc{|d,n| next hook if n==0 proc_call([d,d],n-1,&pr) } proc_call (d,n,&pr) end Warming up -------------------------------------- func_p 86.000 i/100ms func_py 143.000 i/100ms func_m 391.000 i/100ms Calculating ------------------------------------- func_p 1.063k (±59.1%) i/s - 1.032k in 6.066881s func_py 1.435k (± 2.6%) i/s - 7.293k in 5.083872s func_m 3.987k (± 3.6%) i/s - 19.941k in 5.007711s Comparison: func_m: 3986.7 i/s func_py: 1435.5 i/s - 2.78x slower func_p: 1062.7 i/s - 3.75x slower 1.35x faster!! 結論: (今のRubyでrubyで書いた) procはcallせずにyieldしろ! (特に再帰するなら)
  • 8. z ここから裏話 資料が適当になります なんでProc#callが遅いのか-- C level backtrace information ------------------------------------------- /usr/ruby/2.3.1/bin/ruby(rb_vm_bugreport+0x51f) [0x7f7c6570178f] vm_dump.c:688 /usr/ruby/2.3.1/bin/ruby(rb_bug_context+0xd0) [0x7f7c656dbe30] error.c:435 /usr/ruby/2.3.1/bin/ruby(sigsegv+0x3e) [0x7f7c655d5dae] signal.c:890 /lib/x86_64-linux-gnu/libpthread.so.0 [0x7f7c650b4330] /usr/ruby/2.3.1/lib/ruby/2.3.0/x86_64-linux/fiddle.so(rb_fiddle_ptr_aset+0x130) [0x7f7c636699c0] pointer.c:587 /usr/ruby/2.3.1/bin/ruby(vm_call_cfunc+0xf6) [0x7f7c65657f76] vm_insnhelper.c:1638 /usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x15ec) [0x7f7c6565fd9c] insns.def:1893 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f7c65665d43] vm_insnhelper.c:2172 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(ruby_exec_internal+0xc4) [0x7f7c6550c0e4] eval.c:245 /usr/ruby/2.3.1/bin/ruby(ruby_run_node+0x2d) [0x7f7c6550fcad] eval.c:310 /usr/ruby/2.3.1/bin/ruby(main+0x4b) [0x7f7c6550bd4b] addr2line.c:179 -- Ruby level backtrace information ---------------------------------------- test.rb:73:in `<main>' test.rb:15:in `func_p' test.rb:13:in `block in func_p' test.rb:13:in `block in func_p' test.rb:13:in `block in func_p' test.rb:13:in `block in func_p' test.rb:13:in `block in func_p' test.rb:12:in `block in func_p' test.rb:70:in `hook' test.rb:70:in `[]=' /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(invoke_block_from_c_0+0x161) [0x7f7c65664f11] vm.c:971 /usr/ruby/2.3.1/bin/ruby(vm_invoke_proc+0xb8) [0x7f7c65664fe8] vm.c:996 /usr/ruby/2.3.1/bin/ruby(vm_call_opt_call+0xa7) [0x7f7c65665777] vm.c:1072 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x1fe9) [0x7f7c65660799] insns.def:995 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f7c656643d1] vm.c:1650 call毎にCのマシンスタックが沢山積み重なる
  • 10. z なんでyieldが速いのか -- C level backtrace information ------------------------------------------- /usr/ruby/2.3.1/bin/ruby(rb_vm_bugreport+0x51f) [0x7f0977a0978f] vm_dump.c:688 /usr/ruby/2.3.1/bin/ruby(rb_bug_context+0xd0) [0x7f09779e3e30] error.c:435 /usr/ruby/2.3.1/bin/ruby(sigsegv+0x3e) [0x7f09778dddae] signal.c:890 /lib/x86_64-linux-gnu/libpthread.so.0 [0x7f09773bc330] /usr/ruby/2.3.1/lib/ruby/2.3.0/x86_64-linux/fiddle.so(rb_fiddle_ptr_aset+0x130) [0x7f09759719c0] pointer.c:587 /usr/ruby/2.3.1/bin/ruby(vm_call_cfunc+0xf6) [0x7f097795ff76] vm_insnhelper.c:1638 /usr/ruby/2.3.1/bin/ruby(vm_call_method+0xe3) [0x7f097796dd43] vm_insnhelper.c:2172 /usr/ruby/2.3.1/bin/ruby(vm_exec_core+0x15ec) [0x7f0977967d9c] insns.def:1893 /usr/ruby/2.3.1/bin/ruby(vm_exec+0x81) [0x7f097796c3d1] vm.c:1650 /usr/ruby/2.3.1/bin/ruby(ruby_exec_internal+0xc4) [0x7f09778140e4] eval.c:245 /usr/ruby/2.3.1/bin/ruby(ruby_run_node+0x2d) [0x7f0977817cad] eval.c:310 /usr/ruby/2.3.1/bin/ruby(main+0x4b) [0x7f0977813d4b] addr2line.c:179 -- Ruby level backtrace information ---------------------------------------- test.rb:74:in `<main>' test.rb:34:in `func_py' test.rb:26:in `sub' test.rb:32:in `block in func_py' test.rb:26:in `sub' test.rb:32:in `block in func_py' test.rb:26:in `sub' test.rb:32:in `block in func_py' test.rb:26:in `sub' test.rb:32:in `block in func_py' test.rb:26:in `sub' test.rb:32:in `block in func_py' test.rb:26:in `sub' test.rb:31:in `block in func_py' test.rb:70:in `hook' test.rb:70:in `[]=' DEFINE_INSN invokeblock (CALL_INFO ci) (...) (VALUE val) // inc += 1 - ci->orig_argc; { struct rb_calling_info calling; calling.argc = ci->orig_argc; calling.block_handler = VM_BLOCK_HANDLER_NONE; calling.recv = GET_SELF(); val = vm_invoke_block(th, GET_CFP(), &calling, ci); if (val == Qundef) { RESTORE_REGS(); NEXT_INSN(); } 頑張って最適化した人がいるから ruby –dump=insn すると、yieldはinvokeblockという 命令になっていることがわかる。
  • 11. z まとめ def callbug require 'fiddle' Fiddle::Pointer.new(4)[0]=0 end def proc_call (*args) yield *args end ruby –dump=insn Ruby3x3までにはなんとか・・・