���A���F�{�� 25 ���܂ő�����ꂽ Ruby VM �A�h�x���g�J�����_�[�́C���E�̏I���̂��߁C�ۑ����Ă��Ȃ����������������Ă��܂��܂����D����C�������������Ă��������Ǝv���܂��D�����f���������v���܂��D
���A���F���E�̏I���ɂ���Ď���ꂽ�L���𐏎����������Ă��܂����C�������̋L���̂����炪�F���I�ȉ����̂��߂Ɍ������Ă��܂��Ă���悤�ł��D�s�ӁC�����������Ă��������Ǝv���Ă���܂��D
�ꗗ�F
�Ƃ����킯�ŁC Ruby VM �A�h�x���g�J�����_�[�� 25 ���ځC�ŏI���ł��D
�r������ Ruby 2.0.0 �̏Љ�L���݂����ɂȂ��Ă��܂������CVM �܂��̋@�\���Ȃ�ƂȂ��Љ�o������Ȃ����Ǝv���܂��D
���āC2.0 �ł��c�������Ƃ͂��邩�ƌ�����ƁC���ꂪ��R����̂ł��D������ƍׂ������Ƃ�������Ă����Ƒ�ςȂ̂ŁC����l�ɂ�������Ȃ����C����l�Ȃ�ċ���̂��Ȃ��C�Ǝv���悤�ȉӏ������ł܂Ƃ߂Ă݂����Ǝv���܂��D
��R�����Ă����܂����D�v�������炠�ƂŒlj����Ă����܂��ˁD
�������Ă݂�ƁCRuby 2.0.0 �͖{���ɕێ�I�ŁC�\�z�����͂��������ǃh���X�e�B�b�N�ȋ@�\�͂���܂�����ĂȂ��ł��ˁD
Ruby 2.1 �܂łɂȂ�Ƃ��������Ȃ��D
�ł́C�܂����N�D�ǂ����N���D
Ruby VM �A�h�x���g�J�����_�[�� 24 ���ڂł��D
�����̓N���X�}�X�C�u�ł��ˁD�����܂ł�����Ƒ����Ă����ĂƂĂ��ǂ������Ǝv���܂��D
���āC�����͂���܂ł̍������̘b�i���͂͂����œr��Ă���j
Ruby VM �A�h�x���g�J�����_�[�� 21 ���ڂł��D
�X�^�b�N�I�[�o�[�t���[���Ă���܂���ˁD�p�ӂ��ꂽ�X�^�b�N���g�����Ă��܂��Əo��G���[�ł��D�v���O�����ɂ���ĕK�v�ȃX�^�b�N�̃T�C�Y�͈Ⴄ���̂ł����CRuby 1.9 �܂ł̓X�^�b�N�̃T�C�Y���w�肷����@������܂���ł����D
�����ŁCRuby 2.0 �ł͎��� 4 �̊��ϐ��ɂ���āC�X�^�b�N�̐[����ς��邱�Ƃ��o����悤�ɂȂ�܂����D
���ꂼ��X���b�h�ƃt�@�C�o�p�́CVM �̃X�^�b�N�ƃ}�V���X�^�b�N�̃T�C�Y���w��ł��܂��D
�������C�����̒l�͂����܂Ńq���g���ɂȂ��Ă��܂��D�������l���w�肵�Ă��C���̒l�����̃T�C�Y���w�肷�邱�Ƃ͂ł��܂��C�K���Ȑ��ŃA���C������܂��D�������� OS �ɂ���ẮC�X���b�h�̃}�V���X�^�b�N�T�C�Y��ύX���邱�Ƃ��o���Ȃ��ꍇ������܂��D
�����̒l�̓C���^�v���^�N�����ɂ̂ݗL���ł��D�C���^�v���^���N����Ɋ��ϐ��̒l��ω������Ă��C�C���^�v���^�͕ύX�����܂��D
���Ȃ݂ɁC1.9 �̎�������X�^�b�N�T�C�Y���傫���Ȃ��Ă��܂��D����́C�X�^�b�N�T�C�Y���傫���Ă܂����v���O�����͂���܂薳�����炾�낤�C�Ƃ������f�ł��D�����C32bit CPU ���g���Ă���CFiber�i�� Thread�j���ʂɍ쐬����悤�ȃv���O�����̏ꍇ�C���̊��ϐ��𗘗p���ă`���[�j���O���邱�Ƃ��������Ă݂ĉ������D
�����̐ݒ�����s���ɒm�邽�߂ɁC�V�����萔 RubyVM::DEFAULT_PARAMS ����������t�������܂����D
puts RubyVM::DEFAULT_PARAMS
#=>
ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100]
{:thread_vm_stack_size=>131072, :thread_machine_stack_size=>524288, :fiber_vm_stack_size=>65536, :fiber_machine_stack_size=>262144}
����Ȋ����Ŋe�l���i�[���ꂽ�n�b�V���I�u�W�F�N�g�����܂��D����C��������l���lj�����邩������܂���i����Ȃ���������܂���j�D�Ȃ��C�����܂ŎQ�l���Ȃ̂ŁC���̒l�����������Ă��C�C���^�v���^�̋����ɂ͈�؉e����^���܂���D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 20 ���ڂł��D
����� Module#prepend ���Љ�܂����Dinclude �ł̓��\�b�h�T���̏����Ō��ɒlj����Ă������̂��C�O�ɒlj�������̂ł����D
���K�̂��߂ɁC����̃v���O�������Čf���Ă݂܂��D
class C0 def m; p :C0; end end module M def m; p :M; super; end end class C < C0 prepend M # include �������̂� prepend �ɂ��Ă��� def m; p :C; super; end end obj = C.new obj.m #=> ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] :M :C :C0
C �̃I�u�W�F�N�g�Ƀ��\�b�h m �����s�����Ƃ��CM#m ����ɌĂ�Ă��邱�Ƃ��킩��܂��D
����́uModule#prepend �ŁC����܂ŏo���Ȃ������悤�Ȃ��Ƃ��ł���悤�ɂȂ�܂��D�����Ă݂ĉ������D�v�ƌ��̂ł����C������������C�ǂ�Ȏ��Ɏg����ł��傤���D
��Ԃ��肻���Ȏg�����Ƃ��ẮC���郁�\�b�h�̊J�n�ƏI�����ɓ���̏��������������ꍇ�ł��D�Ⴆ�CArray#each ���Ăꂽ�Ƃ��C���O���o�͂���悤�ȗ���L�q���Ă݂܂��D
module EachLogger
def each(*args, &block)
puts "Enter `each'"
super
puts "Leave `each'"
end
end
class Array
prepend EachLogger
end
p :each
[1, 2, 3].each{}
p :find
[1, 2, 3].find(1)
p :find_all
[1, 2, 3].find_all{|e| (e % 2) == 1}
#=>
ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100]
:each
Enter `each'
Leave `each'
:find
:find_all
Enter `each'
Leave `each'
�͂��C���̂悤�� each ���\�b�h�����s���ꂽ�Ƃ��CEachLogger �ɂ���ă��O���o�͂���邱�Ƃ��킩��܂����D
���Ȃ݂ɁCfind ���\�b�h�ł� each �͎g���Ă��Ȃ����Ƃ��킩��܂��D�t�� find_all ���\�b�h�ł͎g���Ă��܂����C����� Enumerable#find_all ���\�b�h�� each ���\�b�h���Ăяo���Ă��邩��ł��D
���̂悤�ɁC���\�b�h�̊J�n�ƏI�����ɉ�������̏������s���Ƃ������Ƃ� around �ƌ������肵�܂��D�������C�J�n�������C�I���������C�Ƃ������Ƃ��o���܂��D
���āC��قǂ� EachLogger �Ƃ��� each ���\�b�h�����M���O���郂�W���[�������܂������C�ǂ����Ȃ炠��N���X�̂��ׂẴ��\�b�h�̃��O���o�͂�����̂�����Ă݂܂��傤�D
def prepend_method_logger klass
mod = Module.new
klass.instance_methods(false).each{|m|
mod.module_eval %Q{
def #{m}(*args)
puts "Enter `#{m}'"
super
puts "Leave `#{m}'"
end
}
}
klass.module_eval{
prepend mod
}
end
class C
def m; puts "C#m"; end
def n; puts "C#n"; end
end
prepend_analyse_module C
obj = C.new
obj.m
obj.n
#=>
Enter `m'
C#m
Leave `m'
Enter `n'
C#n
Leave `n'
prepend_method_logger �͎w�肳�ꂽ�N���X�ɒ�`����Ă��郁�\�b�h���ׂĂɑ��� EachLogger#each �̂悤�ɁC���O���o�͂��郁�\�b�h���`���Ă��܂��Dmodule_eval �𗘗p���Ă���̂������p�I�ł��ˁD
���s���ʂŁCC#m�CC#n �̎��s���ɁC������ƃ��O���o�͂���Ă��邱�Ƃ��킩��Ǝv���܂��D
���āC����𗘗p���āC����������ƕ֗���������Ȃ��c�[��������Ă݂܂��傤�D
����N���X�̃��\�b�h���C�ǂ̂悤�Ȉ������t���C�����ĕԒl�ɉ���Ԃ��Ă���̂����v���Ƃ��Ă݂܂��D�������邱�ƂŁC�Ӑ}���Ȃ��������t���Ă��邩�ǂ������킩��܂��D
def prepend_analyse_module klass
$analyse_result = {} unless defined?($analyse_result)
stat = $analyse_result[klass] = {}
mod = Module.new
klass.instance_methods(false).each{|m|
stat[m] = [Hash.new{|h, k| h[k] = Hash.new(0)}, # args
Hash.new(0)] # return
src = %Q{
def #{m}(*args)
args.each.with_index{|e, i|
$analyse_result[#{klass.name}][:#{m}][0][i][e.class] += 1
}
result = super
$analyse_result[#{klass.name}][:#{m}][1][result.class] += 1
end
}
mod.module_eval src
}
klass.module_eval{
prepend mod
}
end
class C
def m foo, bar; puts "C#m"; end
def n baz; puts "C#n"; end
end
prepend_analyse_module C
obj = C.new
obj.m 'a', 1
obj.m :sym, 1.2
obj.n /x/
require 'pp'
pp $analyse_result
#=>
C#m
C#m
C#n
{C=>
{:m=>[{0=>{String=>1, Symbol=>1}, 1=>{Fixnum=>1, Float=>1}}, {NilClass=>2}],
:n=>[{0=>{Regexp=>1}}, {NilClass=>1}]}}
�F�X�ʓ|�����������̂ŁC$analyse_result �Ƃ����O���[�o���ϐ��ɏ���S���l�ߍ��ނ悤�ɂ��Ă݂܂����D
���ʂ�����ƁCC#m �� 0 �Ԗڂ̈����� String ����� Symbol �� 1 ���C1 �Ԗڂ̈����ɁC... �Ƃ�����킩��܂��D
�����L���ɂ��āC�e�X�g�P�[�X�𑖂点�Ă݂�ƁC�Ӑ}���Ȃ��^�����Ă��邩�ǂ����C�`�F�b�N�ł��邩������܂���D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 19 ���ڂł��D
�����́CRuby 2.0 �œ������ꂽ Module#prepend �ɂ��Ă��Љ�܂��D
�������̒ʂ�CRuby �ł� Module �� include ���邱�ƂŁC���\�b�h��`���g�����邱�Ƃ��o���܂��D
module M def m; p :M; end end class C include M end
���̂Ƃ��CC �I�u�W�F�N�g�̓��\�b�h m �������Ă��邱�ƂɂȂ�܂��D
���Ă����ŁCC �����\�b�h m �������Ă���Ƃ��C�ǂ��Ȃ邩�m���Ă��܂����H
module M def m; p :M; end end class C include M def m; p :C; end end C.new.m #=> :C
C#m �� M#m �ł́CC#m ���g���Ă��邱�Ƃ��킩��܂����D���́Cancestors ������Ƃ킩��܂��D
# ��̃R�[�h�̑������Ǝv���ĉ������D p C.ancestors #=> [C, M, Object, Kernel, BasicObject]
Class#ancestors �̓N���X�̊K�w�\���������܂����C����͂��̂܂܃��\�b�h�̒T�������ɂ��Ȃ��Ă��܂��DC �� M �ł� C �̂ق�����ɗ���̂ŁCC#m ����Ƀq�b�g����̂ł����炪�g����C�Ƃ������Ƃł��ˁD
���߉����ɁCC#m �� super ���Ă݂܂��傤�D
module M def m; p :M; end end class C include M def m; p :C; super; end end C.new.m #=> :C :M
C#m �� super ���� M#m ���Ă�Ă��邱�Ƃ��킩��܂��D
���āCC �� M �� include �����Ƃ��CC -> M �̏��Ƀ��\�b�h����������邱�Ƃ��킩��܂����D�����āCC#m ������C���ꂪ���p����܂��D
�������CC#m ������� M#m ���Ă�ŗ~�����C�Ƃ����ꍇ�͂ǂ���������ł��傤���D���� 1 ���@������܂��DObject#extend ���g���܂��D
class C0 def m; p :C0; end end module M def m; p :M; super; end end class C < C0 def m; p :C; super; end end obj = C.new obj.extend M obj.m #=> :M :C :C0
C �I�u�W�F�N�g�ł��� obj �� extend ���\�b�h�ɂ���� M ���g���������߁C������ M�CC�i������ C0�j�̏��Ƀ��\�b�h���Ă�Ă��邱�Ƃ��킩��܂��D�悩�����悩�����D
���C���ꂾ�� C.new �ō쐬�����I�u�W�F�N�g���ׂĂɑ��� Object#extend ���Ă˂Ȃ炸�s�ւł��i�����āC�I�u�W�F�N�g�̐������x���Ȃ�܂��j�D
������ Ruby 2.0 ����� Module#prepend �Ƃ����@�\���lj�����܂����DModule#include �ł� include ����N���X�̌��ɉ����Ă����̂��C���x�� prepend �ɂ���� �O�ɒlj�����C�Ƃ����@�\�ł��D
�ł͎��ۂɎg���Ă݂܂��傤�D
class C0 def m; p :C0; end end module M def m; p :M; super; end end class C < C0 prepend M # include �������̂� prepend �ɂ��Ă��� def m; p :C; super; end end obj = C.new obj.m #=> ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] :M :C :C0
�����Cobj.m �� M#m�CC#m�i������ C0#m�j�̏��ɒT�������悤�ɂȂ�܂����D�ꉞ�Cancestors �����Ă����܂��傤���D
# �O�q�̃N���X��`������Ǝv���ĉ����� p C.ancestors #=> [M, C, C0, Object, Kernel, BasicObject]
�Ƃ����킯�ŁCC �̑O�� M �����邱�Ƃ��m�F�ł���Ǝv���܂��D
Module#prepend �ŁC����܂ŏo���Ȃ������悤�Ȃ��Ƃ��ł���悤�ɂȂ�܂��D�����Ă݂ĉ������D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 18 ���ڂł��D
����� 2.0 ���玎���I�ɓ������ꂽ Debug Inspector API �̂��Љ�����悤�Ǝv���܂��D�Ȃ��C���̋@�\����ɂ���Ď������ł��̂ŁC���Ƃŕς�邩������܂��C�����Ȃ邩������܂���D�t�B�[�h�o�b�N�C���҂����Ă���܂��D
���āCDebug Inspector API �Ƃ͉����Ƃ����ƁC����X�^�b�N�t���[���̏������o�����Ƃł��D���Ă����ƁCcaller_locations �ł��������C�Ƃ����C�����܂����C����̓X�^�b�N�t���[���̔C�ӂ̃t���[���� Binding �I�u�W�F�N�g�����o���܂��D�܂�C���̃��\�b�h Binding of caller ���ēz�ł��D�����C���p���@�͂�����ƕ��G�ɂȂ��Ă��܂��D�܂��C�p�t�H�[�}���X�������x���̂ŁC���ʂ̃v���O�����̎��s�ł͎g���Ȃ���Ȃ����Ǝv���܂��D�Ƃ������C�g��Ȃ��ʼn������D�����܂ŁC�f�o�b�K�p�ł��D���p���ցD
Debug Inspector API �ƊW����錾�� include/ruby/debug.h ������p���܂��D
/* debug inspector APIs */ typedef struct rb_debug_inspector_struct rb_debug_inspector_t; typedef VALUE (*rb_debug_inspector_func_t)(const rb_debug_inspector_t *, void *); VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data); VALUE rb_debug_inspector_frame_self_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_class_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_binding_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_frame_iseq_get(const rb_debug_inspector_t *dc, long index); VALUE rb_debug_inspector_backtrace_locations(const rb_debug_inspector_t *dc);
�܂��C���p����Ƃ��� rb_debug_inspector_open() ���C���|�C���^ func �Ƌ��ɌĂяo���܂��Drb_debug_inspector_open() �́C���݂̃R���e�L�X�g�ɑΉ����� rb_debug_inspector_t �I�u�W�F�N�g�i�����ł́C�f�o�b�O�R���e�L�X�g�ƌĂт܂��j���쐬���Cfunc �͐������ꂽ�f�o�b�O�R���e�L�X�g�ւ̃|�C���^�ƁCrb_debug_inspector_open() �̑����� data �Ƌ��ɌĂ�܂��D
���������C����Ȋ����ɂȂ�܂��D
VALUE
func(const rb_debug_inspector_t *dc, void *data)
{
...
}
... /* �f�o�b�O�������ӏ��� */
rb_debug_inspector_open(func, some_data_ptr);
...
�f�o�b�O�R���e�L�X�g�ւ̃|�C���^ dc �ɂ���āC���݂̃t���[���̏��ɃA�N�Z�X�ł��܂��D�Ȃ��Cdc �� func ���Ăяo����Ă���Ԃ̂ݗL���ł���Cfunc ����Ԃ������ dc �͉������Ă��܂��܂��̂ł����Ӊ������D
�܂��́Ccaller_locations �����o���܂��傤�Drb_debug_inspector_backtrace_locations(dc) �Ƃ���Ύ��o���܂��D��������o�����ƂŁC�X�^�b�N�t���[���̐[�����킩��܂��i���v���C�T�C�Y��Ԃ� API ��p�ӂ��Ă����悩�����D���߂�j�D����ŁC�X�^�b�N�̐[���� `depth' �ł��邱�Ƃ��킩�����Ƃ��܂��D
n �t���[���ځi�������C0 <= n < depth�j�̃t���[���̏������o�������Ƃ��́Crb_debug_inspector_frame_???_get(dc, n) �Ƃ��Ď��o���܂��D??? �ɁC���o�����������������݂܂��D����ɂ͎��̎�ނ�����܂��D
�������Cbinding �� iseq �� C ���\�b�h�Ȃǂ� nil �ł���\��������܂��Dclass �� TracePoint#defined_class �Ŏ��o���N���X�i���W���[���j�Ɠ��l�ɓ��ك��\�b�h�̏ꍇ�C���كN���X��Ԃ��܂��D
���āC���ꂪ����ƐF�X�Ƃ���炵�����Ƃ��ł���C�����܂��D�ł�����܂藔�p���Ȃ��ʼn������ˁD�厖�Ȃ��ƂȂ̂ŌJ��Ԃ��Ă����܂����C���̋@�\����ɂ���Ď������ł��̂ŁC���Ƃŕς�邩������܂��C�����Ȃ邩������܂���D�t�B�[�h�o�b�N�C���҂����Ă���܂��D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 17 ���ڂł��D
DTrace ���o����悤�ɂȂ�܂����DAaron �����̂������ł��D�Љ�L�������x�������\��Ȃ̂ŁC�ڍׂ͂��������Q�Ƃ��ĉ������i�������Ă��Ȃ��̂ł悭�m��Ȃ��j�D
DTrace �̓����̎d�g�݂ɂ͂��܂�[�����Ă��Ȃ����C���̃g���[�X�̏�������Ƃ͎v���Ă��Ȃ��̂Łi�����C������ƒx���Ȃ邵�C�ȂR�[�h�������j�C�C�͂�����Ƃ��ɁC���̕ӂ͂����������ւ������Ǝv���Ă��܂��D
�ł́C�����͂��̕ӂŁi�蔲���j�D
Ruby VM �A�h�x���g�J�����_�[�� 16 ���ڂł��D
���������N�����Ȃ��悤�ȃR�A�Șb������ꏊ�Ȃ̂ŁC�N�������Ȃ������� TracePoint �̎����ɂ��ďq�ׂ܂��D
vm_trace.c �ɂ���܂��D�����ɂ� set_trace_func ���s�� rb_add_event_hook() �Ȃǂ��܂���������Ă���C���̂��Ƃ�����g���� set_trace_func ����������C����ƕ��s�� TracePoint API ����������Ă���C�Ƃ��������ł��D
Trace �����S�ɖ����ɂ��鏈���ɁC������ƍH�v������܂����C������������Y��ɂȂ��Ȃ����Ǝv���Ă��܂��D
�܂��C���Ƃ͓ǂ߂Δ���܂��D�ȒP�ł��D�����킩��Ȃ��C�Ƃ����ꏊ������܂�����R�����g�������D
�ł́C�����͂��̕ӂŁi�蔲���j�D
Ruby VM �A�h�x���g�J�����_�[�� 15 ���ڂł��D
����܂ŁC3 ��ɓn���� TracePoint �̏Љ�����Ă��܂����D�����́CTracePoint �̋@�\�� C �g�����痘�p���邽�߂� C API �ɂ��Ă��Љ�܂��D
include/ruby/debug.h �Ƃ����t�@�C���������������D�u/* TracePoint APIs */�v�Ƃ����R�����g����n�܂�ӏ�������ɓ�����܂��D
�Z���ł��̂ŁC�S�����p���Ă݂܂��傤�D
VALUE rb_tracepoint_new(VALUE target_thread_not_supported_yet,
rb_event_flag_t events,
void (*func)(VALUE, void *), void *data);
VALUE rb_tracepoint_enable(VALUE tpval);
VALUE rb_tracepoint_disable(VALUE tpval);
VALUE rb_tracepoint_enabled_p(VALUE tpval);
typedef struct rb_trace_arg_struct rb_trace_arg_t;
rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval);
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg);
TracePoint.new �ɑ�������̂� rb_tracepoint_new() �ł��D�����Ɂu�g���[�X��L���ɂ���X���b�h�v�C�u�g���[�X�������C�x���g�v�C�u�g���[�X�ɑ������� C ���̃|�C���^ func�v����сufunc ���ĂԂƂ��ɓn���|�C���^�v���Ӗ����܂��D�Ԓl�� TracePoint �I�u�W�F�N�g�ɂȂ�܂��D�܂��C�킩��܂���ˁD
�X���b�h�̎w�肷��ׂ��p�����[�^���� target_thread_not_supported_yet �ƂȂ��Ă��܂����C�e�X�g���Ă��Ȃ��̂Ŗ��T�|�[�g�Ƃ������Ƃɂ��Ă��܂��D�N���e�X�g���ĉ������D�C�x���g�w��� events �́C�C�x���g��\�����l�̘_���a�ɂȂ�܂��D
���݂� trunk �ł́C�w��ł���C�x���g�� include/ruby/ruby.h �ɉ��L�̂悤�ɒ�`����Ă��܂��D���ꂼ��C���O������Ή����Ӗ����邩�킩��܂���ˁD
/* traditional set_trace_func events */ #define RUBY_EVENT_NONE 0x0000 #define RUBY_EVENT_LINE 0x0001 #define RUBY_EVENT_CLASS 0x0002 #define RUBY_EVENT_END 0x0004 #define RUBY_EVENT_CALL 0x0008 #define RUBY_EVENT_RETURN 0x0010 #define RUBY_EVENT_C_CALL 0x0020 #define RUBY_EVENT_C_RETURN 0x0040 #define RUBY_EVENT_RAISE 0x0080 #define RUBY_EVENT_ALL 0x00ff /* for TracePoint extended events */ #define RUBY_EVENT_B_CALL 0x0100 #define RUBY_EVENT_B_RETURN 0x0200 #define RUBY_EVENT_THREAD_BEGIN 0x0400 #define RUBY_EVENT_THREAD_END 0x0800 #define RUBY_EVENT_TRACEPOINT_ALL 0xFFFF /* special events */ #define RUBY_EVENT_SPECIFIED_LINE 0x10000 #define RUBY_EVENT_SWITCH 0x20000 #define RUBY_EVENT_COVERAGE 0x40000
func �� data �����ł킩���Ȃ����Ǝv���܂��D���Ȃ݂ɁCfunc �̑������́C�������� TracePoint �I�u�W�F�N�g�ɂȂ�܂��D������CTracePoint.new �ɓn���u���b�N�Ɠ����ł��ˁD
���āC�쐬�����g���[�X�͂܂��L���ɂȂ��Ă��Ȃ��̂� rb_tracepoint_enable() �ɂ���ėL���ɂ��܂��D�����ɂ���ɂ� rb_tracepoint_disable() �ł��ˁD
���āC�w�肵���C�x���g����������ƁCfunc �� TracePoint �I�u�W�F�N�g�� data �ƂƂ��ɌĂ�܂��DTracePoint#event �Ȃǂ����s�������킯�ł����C�����ň��ԏ�����K�v������܂��Drb_tracearg_from_tracepoint() �� TracePoint �I�u�W�F�N�g��n���� rb_trace_arg_t �ւ̃|�C���^���擾���ĉ������D�����œ���ꂽ�|�C���^���g���� rb_tracearg_event() �Ȃǂ��Ăяo�����ƂŁC�����擾���邱�Ƃ��o���܂��D
��̓I�ɂ́C���̂悤�ɂȂ��Ȃ����Ǝv���܂��D
void
func(VALUE tpobj, void *data)
{
rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(tpobj);
VALUE event_sym = rb_tracearg_event(trace_arg);
...
}
���Ƃ́C�g�����킩��܂���ˁC���ŁD
�Ƃ����킯�ŁC�삯���ł����CTrcaePoint �� C �g������g�����߂� C API �����Љ�܂����D����ō����ȃv���t�@�C���Ƃ��N������āD
�����ƁC�厖�Ȃ��Ƃ������Y��Ă��܂����Ddebug.h �̐擪������Ə����Ă���
/* Note: This file contains experimental APIs. */ /* APIs can be replaced at Ruby 2.0.1 or later */
�ɒ��ӂ��ĉ������D���̕ӂ� C API �́C�܂��C���������Ȃ̂ŁC�F��Ȃ܂����_�������Ȃ����Ǝv���Ă����ł����C���ۂ��������łɌ������Ă��܂��D�Ȃ̂ŁC�����l�͂��Ƃŕς�����Ƃ��ɒǏ]����o��Ŏg���Ă���ĉ������D�S�����ˁD�܂��C�Ȃs���̈��������������܂�����R�b�\�������ĉ������D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 14 ���ڂł��D
�����́C�ŋߏЉ�Ă��� TracePoint �ׂ̍����g�����̏Љ�����悤�Ǝv���܂��D
����̋L���ł� TracePoint.trace ���g���܂����Dset_trace_func �Ɠ��l�ɁC���̃��\�b�h�I��������ݒ肵���g���[�X���L���ɂȂ�܂��D�������C���ʂ̃I�u�W�F�N�g�̂悤�ɁCTracePoint.new �ɂ���� TracePoint �I�u�W�F�N�g���쐬���邱�Ƃ��o���܂��D�쐬��́C�܂��L���ł͂Ȃ��̂ŁCTracePoint#enable �Ƃ��ăg���[�X��L���ɂ��܂��D���Ȃ݂ɁCTracePoint.new �̈����� TracePoint.trace �Ɠ����ł��D
trace = TracePoint.new(events...){|tp| ... trace ... }
... # �܂��g���[�X�͗L������Ȃ�
trace.enable
... # ���͈̔͂̂݃g���[�X�͗L��
trace.disable
�܂�CTracePoint.trace �Ƃ����̂́CTracePoint.new ���āC����� enable ����Ƃ�����ꑧ�ōs���֗����\�b�h�Ƃ����킯�ł��D
���Ȃ݂� TracePoint#enable �̓u���b�N��^���邱�Ƃ��ł��C���̃u���b�N�����s���̂݃g���[�X��L���ɂ���C�Ƃ����g�������o���܂��D
trace = TracePoint.new(events...){|tp| ... trace ... }
... # �܂��g���[�X�͗L������Ȃ�
trace.enable{
... # ���͈̔͂̂݃g���[�X�͗L��
}
TracePoint#disable ���C���l�Ƀu���b�N��^���邱�Ƃ��ł��C���̃u���b�N�͈̔͂����g���[�X���ɂ��邱�Ƃ��ł��܂��D
���āC�ł͂ǂ̃C�x���g���g���[�X�ł��邩�C�ł�����{�I�ɂ� set_trace_func �łł����g���[�X�{���ƂȂ��Ă��܂��DTracePoint �� rdoc ������p���܂��D
�����܂ł� set_trace_func �Ɠ����ŁC
����炪 TracePoint ����V���ɉ\�ɂȂ����g���[�X�ł���C�x���g�ɂȂ�܂��D�܂��C�Ӗ��͓ǂ߂킩��܂���ˁD
�V���{���œn����悤�ɂ����s����C"c-call" �̂悤�ȃC�x���g���� :c_call �ɂ悤�ɂȂ��Ă��܂��D
���āC���� TracePoint.new �̃u���b�N�ɓn���Ă���u���b�N�p�����[�^�͈�̂Ȃ�Ȃ̂��C�Ƃ������ƂׂĂ݂܂��D�܂��C�N���X�����Ă݂܂��D
trace = TracePoint.trace{|tp|
p tp.class
exit
}
#=> TracePoint
�ǂ����C����� TracePoint �I�u�W�F�N�g�̂悤�ł��D
inspect ���Ē��ׂĂ݂܂��傤�D
trace = TracePoint.trace{|tp|
p [:tp, tp.object_id, tp]
}
p [:trace, trace.object_id, trace]
#=>
ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100]
[:tp, 1476430, #<TracePoint:c_return `trace'@t.rb:1>]
[:tp, 1476430, #<TracePoint:[email protected]:4>]
[:tp, 1476430, #<TracePoint:c_call `object_id'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `object_id'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `p'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `hash'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `hash'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_call `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `inspect'@t.rb:4>]
[:tp, 1476430, #<TracePoint:c_return `inspect'@t.rb:4>]
[:trace, 1476430, #<TracePoint:enabled>]
[:tp, 1476430, #<TracePoint:c_return `p'@t.rb:4>]
������Ƃ킩��Â炭�Ȃ�������Ă܂����C���� TracePoint.new �ō쐬�����I�u�W�F�N�g�ƃu���b�N�p�����[�^�i�����ł� tp�j�͓����I�u�W�F�N�g�ł��iobject_id �������Ȃ̂��킩��Ǝv���܂��j�D�g���[�X���s���Ƃɏ��փA�N�Z�X���邽�߂����̃I�u�W�F�N�g���쐬����̂͌����Ȃ��C�Ǝv���Ă��������v�ɂ��Ă��܂��D
�����I�u�W�F�N�g�ł���Ȃ���Cinspect �̌��ʂ��C�g���[�X���s���ƁC�g���[�X�����s���Ă��Ȃ����ňႤ�̂��킩��܂��D�g���[�X���s���́CTracePoint#inspect �͉��̃C�x���g�Ńg���[�X���ł��邩�C�킩��₷���\�����Ă��܂��D�g���[�X���s���łȂ��Ƃ��́C���� TracePoint �I�u�W�F�N�g�Ŏw�肳���g���[�X���L���ł��邩�ǂ����������Ă��܂��i���̏ꍇ�Cenable �ƕ\�����Ă��܂��ˁj�D
�Ȃ��CTracePoint#enabled? ���\�b�h�ɂ���āC���̃g���[�X���L���ł��邩�ǂ����������Ă��܂��D
�Ō�ɁC�g���[�X���ɂǂ�ȏ���邩���Љ�܂��D
event ���� binding �܂ł́Cset_trace_func �Ŏ�ꂽ���Ƃقړ����ł��D
TracePoint#return_value �́C:return, :c_return, :b_return �C�x���g�̎��̂ݗ��p�ł��郁�\�b�h�ŁCreturn �����������Ƃ��̕Ԓl��n���܂��D���̑��̃C�x���g�������ɂ��̃��\�b�h���Ă�ł���O���������܂��D
TracePoint#raised_exception �́C:raise �C�x���g�̎��̂ݗ��p�ł��郁�\�b�h�ŁC�ǂ̗�O�����������̂���Ԃ��܂��DTracePoint#return_value �Ɠ��l�ɁC���̑��̃C�x���g�������ɂ��̃��\�b�h���Ă�ł���O���������܂��D
���āCTracePoint#defined_class �́Cset_trace_func �ŗ��p�ł��� klass ���Ƃ͎�Ⴂ�܂��i��L�Łu�قځv�ƌ������̂͂��̓_���قȂ邽�߂ł��j�Dset_trace_func �ł́C���ك��\�b�h���Ăꂽ�Ƃ��� klass �ɂ̓I���W�i���̃N���X���n���Ă��܂������CTracePoint#defined_class �ł͓��كN���X���Ԃ�悤�ɂȂ��Ă��܂��D����ɂ���āC���̃��\�b�h�����كN���X���ǂ����킩��悤�ɂȂ��Ă��܂��D
���āCtrace = TracePoint.trace{|tp| ...} �Ƃ����Ƃ��Ctrace �� tp ���C���͓����Ƃ������Ƃł������C�ł� �g���[�X�����s���Ă��Ȃ��Ƃ��ɁCtrace.event �ȂǂƂ���Ƃǂ��Ȃ�ł��傤���D�����͗�O����������C�ł����D
���āC3 ��Ńg���[�X�|�C���g���Љ�܂����D�F�X�Ɩʔ����g�������ł���V�@�\���Ǝv���܂��̂ŁC��������g���Ă݂ĉ������D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 13 ���ڂł��D
����� TracePoint �̗��p�Ⴞ���Љ�܂����D�R�[�h���Čf���܂��i�Ƃ����čs���҂��j�D
def m
p :hello
p :world
end
set_trace_func(proc{|event, file, line, id, binding, klass|
puts "#{file}:#{line} #{id}" if event == 'line'
})
m
#=>
t.rb:10
t.rb:2 m
:hello
t.rb:3 m
:world
����� TracePoint �ŏ����������ł͎��ɁD
def m
p :hello
p :world
end
trace = TracePoint.trace(:line){|tp|
puts "#{tp.path}:#{tp.lineno} #{tp.method_id}"
}
m
#=>
t.rb:10
t.rb:2 m
:hello
t.rb:3 m
:world
�g���[�X��ݒ肵�Ă���Ƃ���͎��̉ӏ��ł��ˁD
set_trace_func(proc{|event, file, line, id, binding, klass|
puts "#{file}:#{line} #{id}" if event == 'line'
})
trace = TracePoint.trace(:line){|tp|
puts "#{tp.path}:#{tp.lineno} #{tp.method_id}"
}
���āC�Ⴂ��������茩�čs���܂��傤�D
�܂��C�o�^�̃C���^�[�t�F�[�X�ɒ��ڂ��Ă݂܂��D
����̗�ł͂��̕Ԓl�ł��� TracePoint �I�u�W�F�N�g�͎g���Ă��܂��Ctrace.disable �Ƃ��邱�ƂŁC���̃g���[�X���������ɂ��邱�Ƃ��ł��܂��D���Ȃ݂ɁC����Ȋ����ł��D
trace = TracePoint.trace{...}
...
trace.disable # �ȍ~�̓g���[�X�������ɂȂ�
...
���ɁC�g���[�X�Ƃ��ēn���u���b�N�����Ă݂܂��D
�Ƃ����킯�ŁC�傫�ȈႢ�Ƃ����������́C���� 4 �ɂȂ�܂��D
���āC��������Ă��� set_trace_func �̖��_�͉��������ł��傤���D�`�F�b�N���Ă݂܂��傤�D
TracePoint.trace �ł́C������ :line �̂悤�ɁC�g���[�X�������C�x���g�̎�ނ��w��ł���̂ʼn������Ă��܂��D
TracePoint.trace �ɂ���ē����� TracePoint �I�u�W�F�N�g�� TracePoint#disable ���\�b�h�ɂ���āC���̃g���[�X�݂̂��ɏo���܂��D
�x�����R�͂���������܂����DProc �I�u�W�F�N�g���Ăяo���R�X�g��������C�Ƃ������̂ł����C(1) �ŋ����̂Ȃ��C�x���g�ł� Proc �I�u�W�F�N�g�Ă�Ȃ��̂ŁCProc �̋N���R�X�g�̖��͎�������Ă��܂��D�܂��CBinding �I�u�W�F�N�g��K���쐬���Ă��܂��C�Ƃ������́Ctp.binding �Ƃ������\�b�h�ɂ���� Binding �I�u�W�F�N�g�̍쐬���w������܂ō쐬����Ȃ��̂ŁC�������肠��܂���D
���ۂɂ��߂��Ă݂܂��傤�D10����̃g���[�X�t���̃��\�b�h�Ăяo���ł��D
require 'benchmark'
def m
a = 1
b = a
a = b
end
max = 100_000
Benchmark.bm{|x|
x.report{
set_trace_func(proc{|event, file, line, id, binding, klass|
if event == 'line'
# do something
end
})
max.times{m}
set_trace_func(nil)
}
x.report{
trace = TracePoint.trace(:line){|tp|
# do something
}
max.times{m}
trace.disable
}
}
���s���ʂł��D
ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100]
user system total real
6.755000 0.016000 6.771000 ( 7.176412)
0.733000 0.000000 0.733000 ( 0.775598)
10 �{�قǑ����Ȃ��Ă��܂��D�Ƃ������Cset_trace_func ���x�����������C�Ƃ������������o���邩������܂���D
�V�K API �Ȃ̂ŁC�C�x���g�𑝂₵�Ă��{���܂���D�܂��CTracePoint.trace �ł́C�g���[�X�������C�x���g���w�肷��悤�ɂȂ��Ă���̂ŁC�Ӑ}���Ȃ��C�x���g�����č���悤�ȃg���[�X�������Ȃ��悤�ɂȂ��Ă��܂��i���Ȃ݂ɁC�������ł͑S�C�x���g���t����悤�ɂȂ��Ă��܂����C�����͎��ȐӔC�ŁD����C������\�������邱�Ƃ��l�����ď����ĉ������j�D����Ȋ����ŁC�݊����̖����������Ă��܂��D
�Ƃ����킯�ŁCTracePoint �ł́Cset_trace_func �Ɋ܂܂�Ă��� 4 �̖����������Ă��邱�Ƃ��킩��܂��D
���āC�����������Ȃ��Ă��܂����̂ŁCTracePoint �ׂ̍����Љ�͖����ɉ��Ƃɂ��܂��D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 12 ���ڂł��D
������ Ruby 2.0 ���瓱�����ꂽ TracePoint �ɂ��Ă��Љ�܂��D
�]�����Cset_trace_func(proc_object) �Ƃ����C���^�[�t�F�[�X������܂����D���܂�����p���܂��D
Ruby �C���^�v���^�̃C�x���g���g���[�X���� Proc �I�u�W�F�N�g�Ƃ��Ďw�肳�ꂽ proc ��o�^���܂��B proc �� nil ���w�肵���ꍇ�Ńg���[�X���I�t�ɂ��܂��B�u���b�N���w�肳�ꂽ�ꍇ�͂��̃u���b�N���g���[�X���� Proc �I�u�W�F�N�g�Ƃ��ēo�^���܂��B
�o�^�����g���[�X�iProc �I�u�W�F�N�g�j�́C�C�x���g���������邽�тɌĂ�܂��D�C�x���g�̎�ނ͎��̂Ƃ���ł��i���܂�����p���܂��j�D
1.9 �ł́C����𗘗p���āCdebug.rb �� profile.rb �Ȃǂ���������Ă��܂����D
�i���Ȃ݂ɁCThread#set_trace_func �Ȃǂ������ł����C����͏ȗ��j
set_trace_func �́i���������Ƃ�����ɂ́j�֗��ȋ@�\�Ȃ̂ł����C��������肪����܂����D
(1) �́C�Ⴆ�� line �C�x���g���������������ȁC�Ƃ����ꍇ���C���ׂẴC�x���g�Ńg���[�X���Ă�Ă��܂����߁Cline �����̏ꍇ�́C�Ⴆ�Ύ��̂悤�ɏ����K�v������܂����D
set_trace_func(proc{|event, file, line, id, binding, klass|
case line
when 'line'
# ...
else
# ���͖�������
end
})
�傫�Ȗ��ł͂Ȃ��ł����C������Ɩʓ|�������ł��ˁD
(2) �́u�����̃g���[�X���C���ꂼ��L���ɂ����薳���ɂ�����ł��Ȃ��v�Ƃ������ł����C�����̃g���[�X��lj����邱�Ƃ͂ł��܂��D�����C�������ʂɖ����ɂ�����@�͂Ȃ��C�S�Ė����ɂ�����@��������܂���D
set_trace_func(proc{|*args| p [1, args]})
set_trace_func(proc{|*args| p [2, args]})
p :hello
set_trace_func(nil) # �����Ŗ����ɂ���
p :world
#=>
c:/ko1/ruby/clean-trunk/bin/ruby: warning: -K is specified; it is for 1.8 compatibility and may cause odd behavior
ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100]
[1, ["c-return", "t.rb", 1, :set_trace_func, #<Binding:0x6fbf1c>, Kernel]]
[1, ["line", "t.rb", 2, nil, #<Binding:0x6fbb84>, nil]]
[1, ["c-call", "t.rb", 2, :proc, #<Binding:0x6fb9a4>, Kernel]]
[1, ["c-return", "t.rb", 2, :proc, #<Binding:0x6fb580>, Kernel]]
[1, ["c-call", "t.rb", 2, :set_trace_func, #<Binding:0x6faf68>, Kernel]]
[2, ["c-return", "t.rb", 2, :set_trace_func, #<Binding:0x6fa874>, Kernel]]
[2, ["line", "t.rb", 4, nil, #<Binding:0x6fa324>, nil]]
[2, ["c-call", "t.rb", 4, :p, #<Binding:0x6f9d84>, Kernel]]
[2, ["c-call", "t.rb", 4, :hash, #<Binding:0x6f96b8>, Kernel]]
[2, ["c-return", "t.rb", 4, :hash, #<Binding:0x6f8cb8>, Kernel]]
[2, ["c-call", "t.rb", 4, :inspect, #<Binding:0x6f81b4>, Symbol]]
[2, ["c-return", "t.rb", 4, :inspect, #<Binding:0x6f37f4>, Symbol]]
:hello
[2, ["c-return", "t.rb", 4, :p, #<Binding:0x6f331c>, Kernel]]
[2, ["line", "t.rb", 6, nil, #<Binding:0x6f2d18>, nil]]
[2, ["c-call", "t.rb", 6, :set_trace_func, #<Binding:0x6f228c>, Kernel]]
:world
1�Ԗڂ�2�Ԗڂ̃g���[�X�����ꂼ����s����Ă���̂��킩��Ǝv���܂����C1�߂��������ɂ���C�Ƃ������@���Ȃ��Ƃ������Ƃ��킩��܂��D
(3) �̒x���Ƃ����̂́C���킸�����ȂȂ̂ł����C�����Ƃ������ꂴ��ׂ���߂ł��D�v���t�@�C����f�o�b�K����肽���C�ȂǂƂ����p�r�ł́C�g���[�X�͏o���邾���Ώۃv���O�����ɉe����^���Ȃ����Ƃ����߂��܂��D
���������C���̋@�\�̓C�x���g���������邽�тɃg���[�X�����s���܂��̂ŁC���̋N���R�X�g��������܂��D�������C(1) �ŏq�ׂ��ʂ�C�����̂Ȃ��C�x���g���������Ă��C����g���[�X�����s�����܂��D�Ⴆ�� line �C�x���g�����g���[�X�������C�Ƃ����ꍇ���C���̃C�x���g�͉��������������܂���ŁC�������邾���ł��R�X�g�������邱�ƂɂȂ�܂��D
�N���R�X�g�ɂ��āC���������ׂ����݂Ă݂܂��ƁC�������� Proc �I�u�W�F�N�g�� call ����R�X�g��������܂��D�������C�������Ԃ�������̂ł�����܂��C�`�����ς���ΎR�ƂȂ�܂��D���́C���\�b�h�Ăяo�������x���ł��i����́C����̉ۑ�ł��j�D�܂��C�u���b�N�̈����ɓn�����I�u�W�F�N�g�̏�������ςł��D�Ƃ��ɁC�C�x���g�����������ӏ��� Binding �I�u�W�F�N�g�����܂����C���ꂪ�d���ł��D�f�o�b�K�p�r�ŗ��p����Ƃ��́CBinding �I�u�W�F�N�g���K�v�ɂȂ�܂����C�v���t�@�C���p�r�ł͕s�v�ȏꍇ�������ł��D�Ƃ����킯�ŁC�K�v��������K�v����Ȃ������肷������̏������C���J�ɂ��Ă���̂Œx���ł��D
���́C�d�l���肨��ю����҂Ƃ��Ă������肪�����āC���ꂪ (4) �C�x���g������ȏ㑝�₹�Ȃ��C�Ƃ����݊����̖��Ȃ̂ł����D�V�����C�x���g��lj����悤�ƍl�����Ƃ��C��قǂ̂悤�ȁC�����̂Ȃ��C�x���g������悤�ȃv���O��������Ȃ�悢�̂ł����C���݂� 8 �̃C�x���g�Ńg���[�X�����s����邱�Ƃ����l�����Ă��Ȃ��v���O�������z�肳��C�݊����ɖ�肪�����܂��D�Ƃ������C�C�x���g��lj��������ȁ[�Ǝv���Ă��̂ł���ˁC�Ԃ����Ⴏ�D
���āCset_trace_func �̖����������邽�߂̐V���ȋ@�\�� TracePoint �ɂȂ�܂��D
�Ⴆ�C�s�����s���ꂽ�Ƃ��Ƀt�@�C�����ƍs�ԍ��C�����ă��\�b�h����\������v���O�����́Cset_trace_func �ŏ����Ɖ��L�̂悤�ɂȂ�܂��D
def m
p :hello
p :world
end
set_trace_func(proc{|event, file, line, id, binding, klass|
puts "#{file}:#{line} #{id}" if event == 'line'
})
m
#=>
t.rb:10
t.rb:2 m
:hello
t.rb:3 m
:world
����� TracePoint �ŏ���������Ǝ��̂悤�ɂȂ�܂��D
def m
p :hello
p :world
end
trace = TracePoint.trace(:line){|tp|
puts "#{tp.path}:#{tp.lineno} #{tp.method_id}"
}
m
#=>
t.rb:10
t.rb:2 m
:hello
t.rb:3 m
:world
���܂�C�Ⴂ�͂Ȃ��悤�ȋC�����܂����C�ׂ����Ƃ��낪�ς���Ă��܂��D������ƋL���������Ȃ��Ă��܂����̂ŁC��̓I�� TracePoint �̏Љ�͖����ɍs�����Ƃɂ��܂��D
�ł͍����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 11 ���ڂł��D
����� Flonum �ɂ��Ă��Љ�܂����D������ Flonum �̎��������Љ�܂��D
�ڍׂ� 2008 �N�ɘ_�����������̂ł��Q�Ɖ������D���{��ł��D
�X���C�h�̂ق������₷���ł��D�����D���ƁC�����ł� Fixnum �� 2 bit�CFloat �� 1 bit �̃^�O���Ƃ��܂������CRuby 2.0 �Ŏ������ꂽ Flonum �ł́CFloat �� 2 bit�CFixnum �� 1 bit�i����܂łƕς�炸�j�Ƃ����悤�Ɏ����������Ă��܂��D
�ɁC�ŏI�I�ɂǂ��������C�X���C�h�ɂ܂Ƃ߂Ă���܂��D
...�������Ƃ���܂�Ȃ̂ŁC�T�v�ł��D
�Ƃ����Ƃ��납��C�n�b�N�������Ă����킯�ł����C���ʓI�ɂ� exponential �̂Ƃ���� 2 bit �ׂ��āC�^�O�ߍ��ނ悤�ɂ��܂����D�ŁC2 bit �ׂ��Ə�����Ă��܂����߁C���߂����������͈͈ȊO�i����Љ�� 1.72723e-77 ���傫�� 1.15792e+77 �ȉ��Ƃ����͈́D����C�������������ȁH�@������Ƃ��������j��������CFlonum ����߂�C�Ƃ����悤�ɂȂ��Ă��܂��D�ŁC���͈̔͂Ƃ����̂� exponential �ł����Ɓi�ȉ����j�C�Ƃ������N�������n�b�N�ɂȂ�킯�ł��D���Ƃ͑f���炵���r�b�g���Z�̐��E�ɗ��Ƃ���킯�ł����C���̕ӂ̍œK���� shinh ����ɒ�Ă��Ē����܂����D�S���t�@�[�����D
��̓I�ɂ́Cinclude/ruby/ruby.h �� VALUE rb_float_new(double)�Cdouble rb_float_value(VALUE) ������ł��D���̐����Ƀt���X�g���[�V���������܂������́i�������܂�Ǝv���j�C���ЃR�[�h��ǂ�ł݂ĉ������D�Z������킩��₷���ł���D
�ł͍����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 10 ���ڂł��D
Ruby 2.0 ����C�|�C���^�� 64bit �ł�����ł� Flonum ������ Float�i���������_���j�̌v�Z�̍��������s���Ă��܂��D�����ɂ����ƁC�������Ǘ��̎��Ԃ������Ă��܂��D
Ruby 1.9 �܂ł́CFloat �̌v�Z���ʂ��ƂɁC�ʁX�̃I�u�W�F�N�g��Ԃ��Ă��܂����D
2.times{
p((1.1 + 1.2).object_id)
}
#=> 5343490
#=> 5343340
�v�Z���ʂł��� 2.3 �Ƃ����I�u�W�F�N�g�ɑ��āC���ꂼ��ʁX�� object_id ���^�����Ă��邱�Ƃ��킩�邩�Ǝv���܂��D�܂�C�ʁX�̃I�u�W�F�N�g�ɂȂ��Ă��܂��D
����́C�S�Ă� Float �̌v�Z�ɓ��Ă͂܂�܂��āC�Ⴆ�� 1.1 + 1.2 + 1.3 �ł��ƁC�܂��� (1.1+1.2) �̌��ʂł��� 2.3 �����܂��āC����� 1.3 �𑫂��� 3.6 �Ƃ����I�u�W�F�N�g��Ԃ��܂��D�܂�C�ŏI�I�ɗ~�����I�u�W�F�N�g�� 3.6 �����Ȃ̂ł����C�����ł� 2.3 �Ƃ����]�v�ȃI�u�W�F�N�g������Ă��邱�ƂɂȂ�܂��D
�m�F���Ă݂܂��傤�i���L�ł́C�I�u�W�F�N�g�X�y�[�X�ɁC���łɕʂ� Float ������̂ŁC1.x �ł͂Ȃ��C100.x �ɕύX���Ă��܂��j�D
x = 100.1 + 100.2 + 100.3
ObjectSpace.each_object(Float){|f|
p f if f > 100
}
#=>
300.6
200.3
100.3
100.2
100.1
Infinity
1.7976931348623157e+308
�]�v�ȃI�u�W�F�N�g�ł��� 200.3 ����������Ă��邱�Ƃ��킩��܂��D���̗�ł� 1 �����̗]�v�ȃI�u�W�F�N�g�ł����Ca0 + a1 + ... + aN �̂悤�� N ��̑����Z������ƁCN-2 �̗]�v�ȃI�u�W�F�N�g������Ă��܂����ƂɂȂ�܂��D
���̂悤�ɁCFloat �I�u�W�F�N�g��������������Ă���ƁC(1) Float �I�u�W�F�N�g�����̃I�[�o�w�b�h (2) GC �̃I�[�o�w�b�h�����ɂȂ�܂��D�Ƃ��ɁC���l�v�Z��p�ɂɍs���Ă���A�v���P�[�V�����̏ꍇ�C��{�I�� Float �I�u�W�F�N�g�͒Z���ł��邽�߁C(2) �����ɂȂ邱�Ƃ������ł��D
�ł́C�����͂ǂ����Ƃ����ƁCFixnum �͈̔͂ł͗]�v�ȃI�u�W�F�N�g�͍��܂���D�Ƃ������CFixnum �I�u�W�F�N�g�� GC �Ώۂ̃I�u�W�F�N�g�ł͂���܂���D�m�F���Ă݂܂��傤�D
n = 1 + 2 + 3
ObjectSpace.each_object(Fixnum){|i|
p i #=> �����o�͂��Ȃ�
}
����́CRuby �����n�iMRI�j���CFixnum ����ʈ������Ă��邽�߂ł��iRHG ��2�� �I�u�W�F�N�g ���Q�Ɓj�D
���ʈ������Ă���̂ŁC�������l�� Fixnum �I�u�W�F�N�g�́C���� object_id �������܂��D��قǂƓ����悤�Ɋm�F���Ă݂܂��傤�D
2.times{
p((11 + 12).object_id)
}
#=> 47
#=> 47
�ǂ���� 47 �ɂȂ�܂����D�܂�C33 �Ƃ��� Fixnum �I�u�W�F�N�g�� object_id �� 33 �Ƃ������Ƃł��i���̐��l���̂́C�����n�ɂ���ĕς�邱�Ƃ�����܂��D�Ⴆ�C64bit �Ńr���h���ꂽ Ruby �ł́C67 �ɂȂ�܂��j�D
�܂��CFixnum ����ʈ������Ă���̂ŁCFixnum �I�u�W�F�N�g�� GC �Ώۂ̃I�u�W�F�N�g�Ƃ��Ă͍쐬���ꂸ�C������ Fixnum �I�u�W�F�N�g�𗘗p���Ă��CGC �͋N����܂���D
GC ���N����Ȃ����Ƃ��m�F���Ă݂܂��傤�D
puts "GC count (before): #{GC.count}"
10_000_000.times{|i|
n = i + i
}
puts "GC count (after): #{GC.count}"
#=>
GC count (before): 4
GC count (after): 4
GC �� 4 ��̂܂ܕς���Ă��Ȃ��̂ŁC���̌J��Ԃ����s���Ă� GC ���������Ă��Ȃ����Ƃ��킩��܂��D���Ȃ݂ɂ��łɁCFloat ���ǂ��Ȃ邩�C�ꉞ�m�F���Ă����܂��傤�D
puts "GC count (before): #{GC.count}"
10_000_000.times{|i|
n = 1.1 + 1.2
}
puts "GC count (after): #{GC.count}"
#=>
ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100]
GC count (before): 1
GC count (after): 776
775 �� GC ���Ă��邱�Ƃ��킩��܂��D
���̂悤�ɁCFixnum �͓��ʈ�������Ă��邪�CFloat �͓��ʈ�������Ă��Ȃ��C�Ƃ����̂����\��傫�������錴���ł����D
�����ŁCFloat �I�u�W�F�N�g����ʈ������� Float �̌v�Z�𑬂����悤�C�Ƃ����̂� Flonum �ł��DFixnum ���ǂ����ʈ�������āC�ǂ̂悤�Ȑ����������Ă������C�Ƃ����̂��܂Ƃ߂�Ǝ��̂悤�ɂȂ�܂��D
�ł́CFlonum ���������������n�ŁC����� 64 bit ���ł� Float �̓������m�F���Ă݂܂��傤�D
s = Hash.new(0)
puts "GC count (before): #{GC.count}"
10_000_000.times{|i|
n = 1.1 + 1.2
s[n.object_id]+=1
}
puts "GC count (after): #{GC.count}"
p s
ObjectSpace.each_object(Float){|f| p f}
#=>
ruby 2.0.0dev (2013-01-24 trunk 38925) [x86_64-linux]
GC count (before): 4
GC count (after): 4
{5404319552844594=>10000000}
NaN
Infinity
1.7976931348623157e+308
2.2250738585072014e-308
���̌��ʂ�����ƁC
�Ƃ������Ƃ��킩��C�ق� Fixnum �Ɠ��������������Ƃ��킩��܂��D
�����CFixnum �Ƃ�����ƈႤ�̂��CObjectSpace �� Float �̃I�u�W�F�N�g�������Ă��܂��ˁD
NaN Infinity 1.7976931348623157e+308 2.2250738585072014e-308
�������Ă��܂��D���́CFlonum �ł͑S�Ă� Float �ł͂Ȃ��C����͈͂� Float �I�u�W�F�N�g����ʈ������C���͈̔͊O�� Float �I�u�W�F�N�g�͏]���ǂ���́CFloat �I�u�W�F�N�g�����܂��D���̓��ʈ�������͈͂Ƃ́C+0.0�C����сC1.72723e-77 ���傫�� 1.15792e+77 �ȉ��͈̔͂ł��i�ׂ������l�͈Ⴄ�����j�D�����C���ʂ̐l�͂��͈̔͂���l�����܂�g��Ȃ��Ǝv���܂��̂ŁC�������� Flonum ���g�����Ȃ����Ǝv���܂��D
����ɔ����CFloat�CFixnum �Ƃ��� freeze �����悤�ɂȂ�܂����D
p 1.frozen? p 1.2.frozen? #=> true true
���āC�ł͊̐S�̐��\�����Ă݂܂��傤�D
require 'benchmark'
Benchmark.bm{|x|
x.report{
10_000_000.times{|i|
n = 1.1 + 1.2
}
}
}
#=>
ruby 1.9.3p385 (2013-02-06 revision 39113) [x86_64-linux]
user system total real
1.760000 0.000000 1.760000 ( 1.761259)
ruby 2.0.0dev (2013-01-24 trunk 38925) [x86_64-linux]
user system total real
1.210000 0.000000 1.210000 ( 1.209062)
2.0 �̂ق��������Ȃ��Ă��邱�Ƃ��킩��Ǝv���܂��D
�ł͍����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 9 ���ڂł��D
����̋L���ł́CObjectSpace::InternalObjectWrapper �Ƃ������̂��o�ꂵ�܂����D���āC����͂��������Ȃ�ł��傤���D
ObjectSpace.reachable_objects_from(obj) �́Cobj �����ڎQ�Ƃ��邷�ׂẴI�u�W�F�N�g��Ԃ��̂ł����C���ɂ� Ruby ����͐G��ׂ��ł͂Ȃ��I�u�W�F�N�g�����݂��܂��D���̂悤�Ȃ��̂̏ꍇ�C��x InternalObjectWrapper �� wrap ���Ă���Ԃ��悤�ɂ��Ă��܂��D
���Ȃ݂ɁC�G��ׂ��łȂ��I�u�W�F�N�g�́C�ʏ�̃��\�b�h�̕Ԓl�ȂǂŎ�邱�Ƃ��o���Ȃ��̂͂������̂��ƁCObjectSpace.each_object �ł���邱�Ƃ͏o���Ȃ��悤�ɂȂ��Ă��܂��D
���ۂɁC�ǂ̂悤�Ȃ��̂����邩�C�����Ă݂܂��傤�D
require 'objspace'
require 'pp'
iseq = RubyVM::InstructionSequence.compile("puts 'hello'")
pp ObjectSpace.reachable_objects_from(iseq)
#=>
[RubyVM::InstructionSequence,
#<InternalObject:0x1062c54 T_ARRAY>,
"<compiled>",
"<compiled>",
#<InternalObject:0x1062c7c T_NODE>]
�����ł́C4�̃I�u�W�F�N�g�����܂����D���̂���2�� InternalObject �ɂȂ��Ă��܂��D�c��2�� "<compiled>" �Ƃ���������́CISeq#path �Ƃ��Ŏ�邽�߂̕�����ł��ˁD
�ł́C�B���ꂽ Array ������ #<InternalObject:0x1062c54 T_ARRAY> �ɁC���������Ă��邩���Ă݂܂��傤�D
require 'objspace'
require 'pp'
iseq = RubyVM::InstructionSequence.compile("puts 'hello'")
hide_array = ObjectSpace.reachable_objects_from(iseq)[1]
pp ObjectSpace.reachable_objects_from(hide_array)
#=>
["hello"]
�����e�����Ƃ��ė��p���� "hello" �Ƃ�����������i�[���Ă���Ƃ������Ƃ��킩��܂����D
���������C�Ȃ����̔z����B���I�u�W�F�N�g�ɂ��Ă��邩�Ƃ����ƁC���̔z��� ObjectSpace.each_object �ȂǂŎ��o���āC����ɕύX��������ƁC���̃o�C�g�R�[�h������s����̂ɖ�肪�����邽�߂ł��D�ŁC���̉B���z��I�u�W�F�N�g���Ȃ������Ƃ����ƁC�o�C�g�R�[�h�����p����I�u�W�F�N�g���C�o�C�g�R�[�h���������Ă��邠������ mark ���邽�߂̔z��ł��D��̓I�ɂ� rb_iseq_t::mark_ary �ł��D
�Ȃ��CInternalObjectWrapper �ɑ��� ObjectSpace.reachable_objects_from ���s���ƁC���� wrap �����Ώۂł�������I�u�W�F�N�g���Q�Ƃ��Ă���I�u�W�F�N�g�Q��Ԃ��܂��D���̋@�\�������邱�ƂŁC�u����I�u�W�F�N�g���N�_�Ƃ����C�I�u�W�F�N�g�̊W�O���t�v�����p�ł��邱�ƂɂȂ�܂��D
����1�����Ă����ƁC����� 1 �Ԗڂɂ��̉B���z��I�u�W�F�N�g������C�Ƃ������Ƃ��킩��܂������C���̏��Ԃ͂Ƃ��ɕۏ���Ă��܂���D��̓I�ɂ́Cmark �����̏��ԂŊi�[����Ă������ƂɂȂ�܂��D
���āCInternalObjectWrapper#object_id �́C������� wrapper �I�u�W�F�N�g�� object_id �����o���܂����Cwrap �����I�u�W�F�N�g�� object_id �����o���������Ƃ�����܂��D������CInternalObjectWrapper#internal_object_id �ɂ���ē��邱�Ƃ��o���܂��D����̋L���ł́C���̋@�\���g���� memsize_of_all_reachable_objects_from(obj) ���������Ă��܂����D
�ł́C�����͂��̕ӂŁD
Ruby VM �A�h�x���g�J�����_�[�� 8 ���ڂł��D
���낻�둧�ꂵ�Ă��܂����D
�����́C
�ŏЉ��Ă��� ObjectSpace.reachable_objects_from(obj) ���l�^�ɂ��Ă݂܂��D�Ȃ��C���̃��\�b�h�� require 'objspace' �Ƃ��āCobjspace ���C�u������ require ���Ȃ��Ǝg���܂���D
ObjectSpace.reachable_objects_from(obj) �́Cobj ���璼�ڒH�邱�Ƃ��ł���I�u�W�F�N�g�����ׂė��ĕԂ��܂��D
���ɗ�������܂��D
(1) �́C��薳���Ǝv���܂����C(2)�C(3) �̈Ⴂ�͂킩��ł��傤���D�����I�u�W�F�N�g����H�邱�Ƃ��o����Ƃ��C1�����Ԃ��Ȃ��悤�ɂȂ��Ă��܂��D
���āC������g���āCobj ����H�邱�Ƃ��ł���C���ׂẴI�u�W�F�N�g���K�v�Ƃ��郁�����T�C�Y���v�Z����R�[�h�������Ă݂܂��D�u���ڂ��ǂ邱�Ƃ��ł���v�ł͂Ȃ��C�u�H�邱�Ƃ��ł���S�ẴI�u�W�F�N�g�v�Ƃ����Ƃ���ɒ��ӂ��ĉ������D�܂�C�ċA�I�� ObjectSpace.reachable_objects_from(obj) ��K�p���悤�C�Ƃ����킯�ł��D
�Ⴆ�C[['a' * 100, 'b' * 100], 'c' * 100] �Ƃ����z��́C������ 100 �̕�����I�u�W�F�N�g 3 �H���̂ŁC���v 300 byte �Əo�ė~�����킯�ł��i�����ɂ́CArray �N���X�I�u�W�F�N�g���H���̂ł����C����͌v�Z���ʓ|�Ȃ̂ŏ��O���邱�Ƃɂ��܂��j�D
����I�u�W�F�N�g������郁�����T�C�Y��ɂ́CObjectSpace.memsize_of(obj) �Ƃ������\�b�h�𗘗p���܂��D����́C1.9 �̎���������Ă��܂��D
�����ł����C�R�[�h�ł��D
require 'objspace'
require 'pp'
def memsize_of_all_reachable_objects_from(obj, exclude_class = Module)
objs = {}
queue = [obj]
while obj = queue.pop
next if objs[obj.object_id]
next unless reachable_objects = ObjectSpace.reachable_objects_from(obj)
reachable_objects.each{|o|
case o
when ObjectSpace::InternalObjectWrapper
next if objs[o.internal_object_id]
else
next if objs[o.object_id]
end
queue.push o if !exclude_class || !o.kind_of?(exclude_class)
}
objs[obj.respond_to?(:internal_object_id) ? obj.internal_object_id : obj.object_id] = obj
end
objs.inject(0){|r, (_, o)| r += ObjectSpace.memsize_of(o)}
end
memsize_of_all_reachable_objects_from(obj, klass=Module) �́Cobj ����H��邷�ׂẴI�u�W�F�N�g�̃T�C�Y��Ԃ��܂��D�������C������ klass �Ŏw�肳�ꂽ�N���X�̃I�u�W�F�N�g�͏��O���܂��D�f�t�H���g�ł� Module �N���X�̃I�u�W�F�N�g�C�܂� Array �Ȃǂ͒H��Ȃ��悤�ɂ��Ă݂܂��Dnil �Ƃ��邱�Ƃŏ��O���Ȃ��悤�ɂȂ�܂��D
�ł́C����Ă݂܂��傤�D
p memsize_of_all_reachable_objects_from([['a' * 100, 'b' * 100], 'c' * 100]) #=> 300
������ 300 ���A���Ă��܂����D
���������Ȃ̂ŁCArray ���܂߂ăT�C�Y������Ă݂܂��D
p memsize_of_all_reachable_objects_from([['a' * 100, 'b' * 100], 'c' * 100], nil) #=> 639428
���炢�����A���Ă��܂����DArray �N���X����H���I�u�W�F�N�g�́C�������ɂ̂ڂ�C���̍��v�T�C�Y���傫���C�Ƃ������ƂɂȂ�܂��i�r���ɂ��� objs �̃G���g���������Ă݂�Ƃ킩��̂ł����C�H�邱�Ƃ��ł��邷�ׂẴI�u�W�F�N�g�� 5604 �������ł��D�������C���ɂ��\��������܂��j�D
memsize_of_all_reachable_objects_from() �́C��r�I�ȒP�ȃ��\�b�h�ł����CObjectSpace::InternalObjectWrapper �Ƃ������̂��g���Ă��邱�Ƃɒ��ӂ��K�v�ł��D����ɂ��ẮC�܂����̋@��ɂ��Љ�܂��i�Ƃ��ăl�^���Ȃ���j�D������������� ext/objspace/objspace.c ��ǂ�ł݂ĉ������D
�ł́C�����͂��̕ӂŁD
���̘b�� RubyConf Taiwan 2012 �̂��߂ɏ����Ă����R�[�h�ł����D
�����Fhttp://www.atdot.net/~ko1/activities/rubyconf.tw2012_ko1.pdf
�����ɂ́C�}�t���Ő���������܂��D�Q�l�ɂ��ĉ������D
Ruby VM �A�h�x���g�J�����_�[�� 7 ���ڂł��D
����̘b�͂��邢����ɏC�������Ă�������̂ŁC������𒍈ӂ��ĉ������D
�Ȃ��C�u���b�N�̒��ŋN�����O�̃N���X�� Timeout::Error �ƈႤ���Ƃ����ƁC������ timeout ���l�X�g�������Ƃ��ɂ����Ƃ킩�邽�߁C�������ł��D
�Ƃ����킯�ŁC�����͂����܂łɂ��Ă����Ă����܂��i�蔲���j�D
���\���K�Ƃ��Ȃ��Ȃ��I���Ȃ��D
Ruby VM �A�h�x���g�J�����_�[�� 6 ���ڂł��D
�{���̓��\�b�h�Ăяo���̍������̘b�̑������������Ǝv���Ă����̂ł����C�\���ς��Ĕ��C�x���g�ɂ��Ă̘b���������Ǝv���܂��D
�Ƃ肠���������Ă����ƁCRuby 2.0 ���� timeout(3){loop{}} �̂悤�ȃv���O�������I���Ȃ��Ȃ肻���ł��i�ڍׂ͈ȉ��j�D�������̃v���O�����ŁC���̂悤�ȗႪ�������m�F���Ă݂ĉ������i���ۂɁC�������̃v���O�������ŐV�� trunk �Ńe�X�g���Ē����̂������ł��j�D�����C���̂悤�ȗႪ�݊����ɂ��ĂƂĂ����C�Ƃ������ƂɂȂ�悤��������C���̋����͕ύX�����\��������܂��D
timeout(30) { ... } �Ə����Ă����ƁC30�b�ソ���Ă��u���b�N�����s���̏ꍇ�C�u���b�N�� Timeout::Error ��O�ɂ�蒆�f����܂��D
require 'timeout'
timeout(30){
sleep 40
}
#=> t.rb:3:in `sleep': execution expired (Timeout::Error)
����͂ǂ�����Ď������Ă��邩�Ƃ����ƁCtimeout �u���b�N�����s���鎞�ɃX���b�h������1���ĂāC���̃X���b�h�� 30 �b��Ƀu���b�N���s���̃X���b�h�� Thread#raise ���g���� Timeout::Error ���\�b�h�������܂��D30 �b�ȓ��Ƀu���b�N���I�������ꍇ�́C���̃^�C���A�E�g�𓊂��Ă���X���b�h���~���邱�Ƃŗ�O�������Ȃ��悤�ɂ��܂��D
���Č����͊ȒP�Ȃ̂ł����C����ɂ͎��̂悤�Ȗ�肪����܂����D
require 'timeout'
timeout(30){
begin
... # ���� X
ensure
... # ��n������
end
}
���̂悤�ȃv���O�������N�����Ƃ��C���� X �̌�ŁC�K����n�����������邱�Ƃ����҂���܂��D�Ⴆ�C�t�@�C�����������肾�Ƃ��D
�������C���� X ���� Timeout::Error �����������̂Ȃ�ǂ��̂ł����C��n�������̍Œ��� Timeout::Error ����������Ƃ܂������ƂɂȂ�܂��D
���̂悤�Ȗ��ɑΏ����邽�߂ɁCThread.async_interrupt_timing �Ƃ������̂���������܂����i���O�͕ύX�����\��������܂��D�Ƃ������C�����ύX���܂��j�D
�ʓ|�������b�͒u���Ƃ��āC���̏ꍇ�ǂ�����Ďg�����Ƃ����ƁCThread.async_interrupt_timing(Timeout::Error => :defer) { ... } �Ƃ��Ă����ƁC���̃u���b�N�̕����ł� Timeout::Error ��O�����Ă������i�u���b�N���甲�����Ƃ��͕��ʂɗ�O��������܂��j�ƂȂ�܂��i���Ȃ݂ɁC:defer �Ƃ����V���{�������C�ς��\��������܂��D�V�����d�l�Ȃ̂ŁC�܂����O�ŔY��ł���̂ł��j�D
�t�ɁCThread.async_interrupt_timing(Timeout::Error => :immediate) �Ǝw�肷��ƁC�����ɗ�O���オ�邱�ƂɂȂ�܂��D
������g���āC��n���̍Œ��ɗ�O�������N���Ȃ��悤�ɂ���ƁC���̂悤�ɏ����܂��D
require 'timeout'
Thread.async_interrupt_timing(Timeout::Error => :defer){
# �����ł͈�� Timeout::Error �͎��Ȃ��i���f���Ȃ��j
timeout(30){
begin
Thread.async_interrupt_timing(Timeout::Error => :immediate){
... # ���� X�D�����ł� Timeout::Error �ɂ���Ē��f�����
}
ensure
... # ��n�������D�����ł͈�� Timeout::Error �͎��Ȃ��i���f���Ȃ��j
end
}
}
���������C��n�������̒��� Timeout::Error �Œ��f����邱�Ƃ��Ȃ����߁C���S�Ɍ�n�����������Ƃ��o���܂��D
���Ȃ݂ɁC
require 'timeout'
timeout(30){
begin
... # ���� X�D�����ł� Timeout::Error �ɂ���Ē��f�����
}
ensure
Thread.async_interrupt_timing(Timeout::Error => :defer){
... # ��n�������D�����ł͈�� Timeout::Error �͎��Ȃ��i���f���Ȃ��j
}
end
}
�������̂ق����ȒP�ł�������Ȃ����C�ƌ����邩������܂��C���ꂾ�� ensure ���n�܂����u�Ԃ� Timeout::Error ����M���Č�n�������������Ȃ��Ȃ��Ȃ�C�Ƃ����댯������܂��D���Ȃ݂ɁC���݂� MRI �̎����ł́C���̃^�C�~���O�ł͔��C�x���g���N���肦�Ȃ��̂ŁC���̐S�z�͂Ȃ��̂ł����C��ʓI�ɂ͋C��t����ׂ��ł��傤�D
���āC���� timeout ���������Ƃɂ��̂悤�ɏ璷�ȋL�q������͖̂ʓ|�Ȃ̂ŁC�݂�ȏ����Ȃ��Ȃ� �� �ςȂƂ���� Timeout::Error ���N����悤�ȃv���O�����ɂȂ��Ă��܂��C�Ƃ������O������܂��D
�����ŁC[Bug #7503] make timeout.rb async-interrupt safe by default �ɂ����āCtimeout �̋�����ς��Ă��܂����Ƃ����ύX�����肳��ɂ���Ă���Ă��܂��i����C�o�O����Ȃ���Ȃ��j�D
��قǁCThread.async_interrupt_timing �ł� :never�i��O�������Ȃ��j �� :immediate�i��O�������ɏグ��j�C�Ƃ����w������܂������C������C:on_blocking �Ƃ����w�肪����܂��i�������悤�ł����C:on_blocking �Ƃ������O�͕ύX�����\��������܂��j�D
���� :on_blocking �Ƃ����w�������ƁC�w�肳�ꂽ��O���C��� I/O �����܂Œx�����邱�Ƃ��o���܂��D�O������̗�O�ɂ���Ē��f�����������p��̑����� I/O �̒��f�Ȃ̂ŁC����Ŏ������C�Ƃ����������o���܂��D
[Bug #7503] �̒�Ăł́C�utimeout �Œ��f�ł���u���b�N���C:on_blocking �ň͂�ł����āC���f�� I/O �����Ȃǂ̃^�C�~���O�ł����o���Ȃ��悤�ɂ��悤�v�Ƃ������̂ɂȂ��Ă��܂��D���̂悤�ɂ��邱�ƂŁCensure �ł̌�n���Ȃǂ̊ԂɊ��荞�܂�邱�Ƃ�h�����Ƃ��o���܂��D
�������C����ɂ͌݊����ɖ�肪����C�Ⴆ�� I/O �����̊܂܂Ȃ��v�Z�� timeout �Ńf�t�H���g�ł͒��f�ł��Ȃ��悤�ɂȂ��Ă��܂��D
require 'timeout'
timeout(30){
# ���Ԃ̂�����v�Z�iI/O�����j
]
�������́C�������[�v�𒆒f�o���Ȃ��Ȃ�܂��D
require 'timeout'
timeout(30{
loop{} # �������[�v
}
�܂��C��҂��܂Ƃ��ɏ����l�͋��Ȃ��Ƃ͎v���܂����C�O�҂͂��蓾���Ȃ��́C�Ƃ����C�����Ă��܂��i�Ȃ̂ŁC�݊���100%�Ƃ����ڕW���f���Ă��� Ruby 2.0 �ɓ���ėǂ��̂����͂���܂���C����Ȃ��̂ł��j�D
���̂悤�ɁC�]���ʂ葦���ɒ��f���ė~�����Ƃ��́Ctimeout(sec, immediate: true) �̂悤�ɌĂׂΗǂ��C�Ƃ������Ƃł���C�������������Ɠ����܂��D�u���̏��������Ăˁv�Ƃ����ċ��e�ł��邩�ǂ����C�����̏C���̌݊����I�ȃL���ɂȂ�܂��D
�Ƃ����킯�ŁC����͎���3�̂��Љ�ł����D
�ł͍����͂��̕ӂŁD
���H�c��`���ې��^�[�~�i���ŏ���p�D���̍ł��ǂ�ǂ߂Ă̂��Ƃ��o������Ă̂͂��肪�������Ƃ��Ȃ��D����C��������Ƃ��Ȃ����Ƃ���Ȃ��ǂ��D
Ruby VM �A�h�x���g�J�����_�[�� 5 ���ڂł��D
�o�b�N�g���[�X�̘b���������̂ŁC������ƕʂ̘b�����܂��D
���N�� RubyConf 2012 �ŁC���\�b�h�̍������̘b�����܂����D Ruby �̓��\�b�h�Ăяo�����R�s���̂ŁC���\�b�h�̍������͑厖�ł��D
Ruby 2.0 �ł́Csend ���\�b�h�̍œK����F�X�ƍs���Ă��܂��D���\�ł́C�����̒��̃G�b�Z���X���Љ�܂����D���\������ http://www.atdot.net/~ko1/activities/rubyconf2012_ko1_pub.pdf �ɂ���̂ŁC�Q�l�ɂ��Ă݂ĉ������D
�����͂��̕ӂŁi�蔲���j�D
RSS �̐����^�C�~���O���[�� 0 ���iJST�j�Ȃ̂ŁC�Ȃ��ڂ��Ă�悤�Ɍ����Ă������ȁD
Ruby VM �A�h�x���g�J�����_�[�� 4 ���ڂł��D
����܂ŁCRuby 2.0 ���瓱������� caller �܂��̘b�����Љ�Ă��܂����D�����̓o�b�N�g���[�X�܂��̍Ō�̘b�ł��D�����D
Ruby �ł́C��O�������Ƀo�b�N�g���[�X��ۑ�����܂��D�ۑ����Ă����Ȃ��ƁC���ƂŁi�Ⴆ�X�^�b�N�������߂�����Łj���̏����Q�Ƃł��Ȃ����߂ł��D
Ruby 1.9 �ȑO�ł́C��O�������� caller ���Ԃ��悤�ȃo�b�N�g���[�X���i������̔z��j�����C��O�I�u�W�F�N�g���ێ����Ă���悤�ɂȂ��Ă��܂����D�������C����͂�����ƒx���ł��D�t���[���T�C�Y���C������I�u�W�F�N�g�����āC�z��Ɋi�[���Ȃ���Ȃ�܂���D
�����ŁCRuby 2.0 �ł́C��O�������ɂ� Thread::Backtrace �Ƃ����I�u�W�F�N�g�����邱�Ƃɂ��܂����D����́CException �I�u�W�F�N�g����͒��ڂ͎Q�Ƃł��Ȃ�����ȃI�u�W�F�N�g�ɂȂ��Ă��܂��iObjectSpace.each_objects �Ŋ撣��ΎQ�Ƃł��܂��j�D
Exception#backtrace ���Ăꂽ�Ƃ��CThread::Backtrace �I�u�W�F�N�g����z��ɂ��鏈��������C�]���́icaller ���Ԃ��悤�ȁj������z������߂č쐬���܂��D���̂悤�ɂ��邱�ƂŁCException#backtrace ���Q�Ƃ��Ȃ��ꍇ�i����t���[�Ƃ��ė�O�𗘗p���Ă���悤�ȏꍇ�j�̃I�[�o�w�b�h���팸���Ă��܂��D
�ł́C���ۂɑ����Ă݂܂��傤�D
require 'benchmark'
def rec n=100, &b
n == 0 ? yield : rec(n-1, &b)
end
max = 100_000
Benchmark.bm{|x|
x.report(" 10"){
max.times{
begin
rec(10){raise}
rescue # ignore raise
end
}
}
x.report("100"){
max.times{
begin
rec(100){raise}
rescue # ignore raise
end
}
}
}
__END__
ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100]
user system total real
10 rec 2.262000 0.031000 2.293000 ( 2.352799)
100 rec 10.437000 0.141000 10.578000 ( 10.638851)
ruby 2.0.0dev (2012-12-01 trunk 38127) [i386-mswin32_100]
user system total real
10 rec 0.640000 0.015000 0.655000 ( 0.652583)
100 rec 2.199000 0.031000 2.230000 ( 2.280790)
�S�X�^�b�N�t���[���́C�o�b�N�g�[���X�������邽�߂ɕK�v�ɂȂ��� (*1) ��ۑ�������̂ŁC�ǂ����Ă��X�^�b�N�g���[�X�̃T�C�Y�ɔ�Ⴕ�����Ԃ������邱�ƂɂȂ��Ă��܂��܂����C������ 1.9 �ɔ�ׂĐ����Ƒ����Ȃ��Ă��邱�Ƃ��킩��̂ł͂Ȃ��ł��傤���D
(*1) ��̓I�ɂ� iseq + pc �ɂȂ�܂��D�{���͂���������ƕ��G�ł����D
�i��O�I�ɂ�����������Ȃ���O�̐����������Ȃ��āC�������l�͌���I���Ƃ͎v���܂���...�j
�Ȃ��Ccaller ����� caller_locations �́C���� Thread::Backtrace �I�u�W�F�N�g��1�x�������Ă���C������x�[�X�ɕ�����̔z��C�������� Thread::Backtrace::Location �̔z������܂��D
�Ƃ����悤�ɁCRuby 2.0 ����o�b�N�g���[�X�܂��̍\����������ƕς��܂����D�ڂ����m�肽���l�� vm_backtrace.c ��ǂ�ł݂ĉ������D
�ł́C���̕ӂŁD
�O���V�傪������ꂽ�̂ŁC���낻��͐s���邩������Ȃ��D
Ruby VM �A�h�x���g�J�����_�[�� 3 ���ڂł��D
�������CRuby 2.0 �̐V�@�\�̂��Љ�ł��D
��� ���Љ�� caller_locations �ł����C������g�����ƂŊȒP�Ƀp�X���Ȃǂ��������o�����Ƃ��ł��܂��D�܂�Ccaller �ŕK�v�ł������p�X���̐�o���̂悤�Ȑ��K�\���̌Ăяo���Ȃǂ��s�v�ɂȂ�܂��D��������ƁC�܂�C���\���ǂ��Ȃ�̂ł��D
caller ���v���t�@�C���Ȃǂɗ��p���悤�Ƃ���Ƃ��C���\�͂ƂĂ��厖�ɂȂ�܂��i���\�͑厖�D�����C�e�X�g�ɏo�܂��j�D
�ł́C�������Ă݂܂��傤�D���K�\���Ő�o���łƁCpath ���\�b�h�����Ŏ��o���ł����C���Ԃ��v���Ă݂܂����D
require 'benchmark'
max = 100_000
Benchmark.bm{|x|
x.report{
max.times{
/(.+):\d/ =~ caller(0)[0]
}
}
x.report{
max.times{
caller_locations(0)[0].path
}
}
}
#=>
ruby 2.0.0dev (2012-12-01 trunk 38127) [i386-mswin32_100]
user system total real
1.872000 0.000000 1.872000 ( 1.882239)
0.312000 0.000000 0.312000 ( 0.315540)
path ���\�b�h�Ŏ��o���ł́C6 �{���x�������Ƃ��킩��܂��D�܂��C����Ⴛ���ł���ˁD
�i�Ȃ��C�����ł͂��傤�e�L�g�[�Ȑ��K�\�����g���Ă��邽�߁C":" ���܂ނ悤�ȃp�X���͐������p�[�X�ł��܂���D���̕ӂ��Cpath ���\�b�h���g�������b�g�ł��ˁj
���āC���\���l����ƁC���������u1��̃t���[�������v���̂Ȃ�C1�ゾ���Ԃ��Ă��������̂Ɂv�Ƃ������ƂɂȂ�܂��D
Ruby 2.0 ����CKernel#caller ����� Kernel#caller_locations �͑�2���� n ����邱�Ƃ��ł��C����̓X�^�b�N�̐[���ꏊ���� n ���o���C�Ƃ����Ӗ��ɂȂ�܂��D����Ă݂܂��傤�D
def m p caller(0) #=> ["t.rb:2:in `m'", "t.rb:7:in `<main>'"] p caller(0, 1) #=> ["t.rb:3:in `m'"] p caller(0, 2) #=> ["t.rb:4:in `m'", "t.rb:7:in `<main>'"] end m
���������ƁC�S�����o���C1 �Ǝw�肷��� 1 �������o���C�Ƃ������Ƃ��킩�����Ǝv���܂��D
�ł́C���ꂪ���\�ɂǂꂭ�炢�e�����邩���Ă݂܂��傤�D
require 'benchmark'
max = 100_000
Benchmark.bm{|x|
x.report("caller w/o 2nd arg"){
max.times{
caller(0)[0]
}
}
x.report("caller w/ 2nd arg"){
max.times{
caller(0, 1)[0]
}
}
x.report("caller_loc w/o 2nd arg"){
max.times{
caller_locations(0)[0]
}
}
x.report("caller_loc w/ 2nd arg"){
max.times{
caller_locations(0, 1)[0]
}
}
}
#=>
ruby 2.0.0dev (2012-12-01 trunk 38127) [i386-mswin32_100]
user system total real
caller w/o 2nd arg 1.513000 0.000000 1.513000 ( 1.555697)
caller w/ 2nd arg 0.265000 0.000000 0.265000 ( 0.259033)
caller_loc w/o 2nd arg 0.297000 0.000000 0.297000 ( 0.298538)
caller_loc w/ 2nd arg 0.093000 0.000000 0.093000 ( 0.090512)
��2�����Ŏw�肵�����̂������Ƒ������Ƃ��킩��܂��D
�Ȃ��C����̓X�^�b�N�t���[���̃T�C�Y���傫���Ƃ�茰���ɂȂ�܂��i���Ȃ݂ɁC���̂Ƃ��̃X�^�b�N�t���[���̃T�C�Y�� 9 �ł����j�D
���߂��ɁC100�قǑ����āi�܂�C109�t���[���j�ő����Ă݂܂��傤�D
require 'benchmark'
def rec n=100, &b
n == 0 ? yield : rec(n-1, &b)
end
max = 100_000
Benchmark.bm{|x|
x.report("caller w/o 2nd arg"){
rec{
max.times{
caller(0)[0]
}
}
}
x.report("caller w/ 2nd arg"){
rec{
max.times{
caller(0, 1)[0]
}
}
}
x.report("caller_loc w/o 2nd arg"){
rec{
max.times{
caller_locations(0)[0]
}
}
}
x.report("caller_loc w/ 2nd arg"){
rec{
max.times{
caller_locations(0, 1)[0]
}
}
}
}
#=>
ruby 2.0.0dev (2012-12-01 trunk 38127) [i386-mswin32_100]
user system total real
caller w/o 2nd arg 19.172000 0.188000 19.360000 ( 19.644995)
caller w/ 2nd arg 0.500000 0.015000 0.515000 ( 0.530067)
caller_loc w/o 2nd arg 3.478000 0.000000 3.478000 ( 3.494444)
caller_loc w/ 2nd arg 0.297000 0.031000 0.328000 ( 0.335042)
�Ȃ�ƁC��40�{���Ⴂ�܂��DRaila �Ȃǂ̃t���[�����[�N�𗘗p����ƁC�X�^�b�N�t���[�����傫���Ȃ邱�Ƃ������̂ŁC���� caller ��1�t���[�����������~�����C�Ƃ������͊��p���Ă��������D
���āCRails �Ƃ����Ⴊ�o�Ă����̂ŁC�����̍Ō�̘b����Љ�܂��D
Rails �Ȃǂ̃t���[�����[�N�̏ꍇ�C�X�^�b�N�̐[���Ƃ���̃t���[���̓t���[�����[�N�̕��ł���C�����̂���A�v���P�[�V�����̃X�^�b�N�t���[���͐Ƃ���̈ꕔ�����C�Ƃ������Ƃ�����܂��D�܂�Ccaller �̕����z������o�������C�Ƃ����p�r�ł��D
�����ŁCcaller ����� caller_locations �͑������� Range ����悤�ɂȂ�܂����D
caller(2..8) �Ƃ���ƁC2�ォ��8��܂ł�6�t���[�����̏������o���܂��D�܂��C�t���[�����[�N�̃X�^�b�N�t���[����n����Ă��邱�Ƃ��킩���Ă���Ccaller(1..-n) �Ƃ��邱�ƂŁC1��̃t���[������C�S�X�^�b�N�t���[���̃T�C�Y - n �̕����X�^�b�N�t���[�������o�����Ƃ��ł��܂��D
������Ƃ킩��Â炢�ł����CArray#[range] �ƑS�������悤�ɍ���Ă���܂��̂ŁC�������� Array#[range] �̎g���������ĉ������D
���Ȃ݂ɁC�����Љ����2�����̒lj��C����ё�1������ Range ������悤�ɂ���g���́CThread#backtrace ����� Thread#backtrace_locations �ɂ��s���Ă��܂��D
�ł́C�����͂��̕ӂŁD
caller �W�����łĂ��ˁ[����ˁ[���I
�ł��C����������Ƃ��������̂���D
http://gihyo.jp/news/info/2012/12/0101 �ɕ⑫����Ȃ��āC��͂芨�Ⴂ���Ă���悤�ŁC�����ł��D���ꂩ������Ⴂ���Ă��������D
Ruby VM �A�h�x���g�J�����_�[�� 2 ���ڂł��D
�������CRuby 2.0 �̐V�@�\�̂��Љ�ł��D
����܂ŁC���݂̎��s�ӏ��̃o�b�N�g���[�X�����擾���邽�߂� Kernel#caller �Ƃ������\�b�h������܂������C�������g���₷������ Kernel#caller_locations �Ƃ������\�b�h����������܂����D
�o�b�N�g���[�X���Ƃ́C���s���̃X���b�h���C�ǂ�ȃ��\�b�h�Ăяo���i����уu���b�N�Ăяo���j���s���Ă��邩�C�Ƃ������̂��������ŁC��O�������ɏo�͂����悤�Ȃ��̂ł��D
require 'pp' def m1 raise end def m2; m1; end def m3; m2; end def m4; m3; end def m5; m4; end pp m5 #=> t.rb:4:in `m1': unhandled exception from t.rb:7:in `m2' from t.rb:8:in `m3' from t.rb:9:in `m4' from t.rb:10:in `m5' from t.rb:12:in `<main>'
���Ȃ݂ɁC��O�������̃o�b�N�g���[�X���́CException#backtrace �ɂ���Ď擾���邱�Ƃ��ł��܂��D
require 'pp' def m1 raise end def m2; m1; end def m3; m2; end def m4; m3; end def m5; m4; end begin pp m5 rescue => e pp e.backtrace end ["t.rb:4:in `m1'", "t.rb:7:in `m2'", "t.rb:8:in `m3'", "t.rb:9:in `m4'", "t.rb:10:in `m5'", "t.rb:13:in `<main>'"]
���āC���݂̃o�b�N�g���[�X���擾���邽�тɖ����O���o���Ă��Ă͑�ςȂ̂ŁCKernel#caller ���\�b�h�����݂��܂��D
require 'pp' def m1 caller end def m2; m1; end def m3; m2; end def m4; m3; end def m5; m4; end pp m5 #=> ["t.rb:7:in `m2'", "t.rb:8:in `m3'", "t.rb:9:in `m4'", "t.rb:10:in `m5'", "t.rb:12:in `<main>'"]
Exception#backtrace �Ŏ��o�����o�b�N�g���[�X���ɂ���ׂāC`m1' ���\�b�h���s���ł���C�Ƃ���������Ă��܂��ˁDcaller ���\�b�h�͑������ɐ����l�����C���ڂ̃o�b�N�g���[�X���擾����̂��C�Ƃ����w�肪�s���C�f�t�H���g�l�� 1 �ɂȂ��Ă��܂��D�܂�C1 ��̃g���[�X���擾����C�Ƃ������ƂɂȂ�܂��D����� 0 �ɂ���ƁC���݂̃t���[���ʒu�̃g���[�X���擾���邱�Ƃ��ł��܂��D
require 'pp' def m1 caller(0) end def m2; m1; end def m3; m2; end def m4; m3; end def m5; m4; end pp m5 #=> ["t.rb:4:in `m1'", "t.rb:7:in `m2'", "t.rb:8:in `m3'", "t.rb:9:in `m4'", "t.rb:10:in `m5'", "t.rb:12:in `<main>'"]
����ŁCException#backtrace �Ɠ����\���ɂȂ�܂����D�Ȃ��C�Ȃ��f�t�H���g�l�� 1 �ł��邩�C�ł����C�����������[�X�P�[�X��������������C�ł����˂��D
���Ȃ݂ɁC���̃X���b�h�̌��݂̃o�b�N�g���[�X���͉����C�Ƃ������Ƃׂ� Thread#backtrace �Ƃ������\�b�h�����݂��܂��D
require 'pp'
def m1
sleep
end
def m2; m1; end
def m3; m2; end
def m4; m3; end
def m5; m4; end
th = Thread.new{
m5
}
sleep 0.1
pp th.backtrace
#=>
["t.rb:4:in `sleep'",
"t.rb:4:in `m1'",
"t.rb:7:in `m2'",
"t.rb:8:in `m3'",
"t.rb:9:in `m4'",
"t.rb:10:in `m5'",
"t.rb:13:in `block in <main>'"]
Thraed#backtrace ���\�b�h�𗘗p���邱�ƂŁC�X���b�h th �́C�� sleep �ŐQ�Ă���C�Ƃ������Ƃ��킩��܂��ˁD
���āC1.9 �܂ł� caller �ł́C��L�̂悤�� "#{path}:#{lineno} #{method_name}" �̂悤�Ȍ`�̕�����̔z�Ԃ��Ă��܂��D�����C���X path �����Clineno �����Cmethod_name �������~�����C�Ƃ����ꍇ������܂��D���̏ꍇ�C���K�\���Ȃŕ�������o���Ȃ���Ȃ�܂���D
�����ŁCRuby 2.0 ���� Kernel#caller_locations �Ƃ������\�b�h�����������\��ł��i�����j�Dcaller �Ɠ����g�����Ŏg����̂ł����C�Ԃ��Ă���l�� Thread::Backtrace::Location �Ƃ����N���X�̃I�u�W�F�N�g�ɂȂ�܂��D������ƒ����ł����C�ӂ[�̐l�́C���̃N���X�����������Ƃ͖����̂ŋ����ĉ������D
�ł́Ccaller �̑���� caller_locations ���g���Ă݂܂��D
require 'pp' def m1 caller_locations end def m2; m1; end def m3; m2; end def m4; m3; end def m5; m4; end pp m5 #=> ["t.rb:7:in `m2'", "t.rb:8:in `m3'", "t.rb:9:in `m4'", "t.rb:10:in `m5'", "t.rb:12:in `<main>'"]
�͂��C�������Ɠ������ʂ������܂����ˁD�����悤�ȕ\���ɂȂ��Ă��܂��̂ł�����Ƃ킩��Â炢�̂ŁC�e�v�f�̃N���X���m�F���Ă݂܂��傤�D
require 'pp'
def m1
caller_locations
end
def m2; m1; end
def m3; m2; end
def m4; m3; end
def m5; m4; end
pp m5.map{|e| e.class}
#=>
[Thread::Backtrace::Location,
Thread::Backtrace::Location,
Thread::Backtrace::Location,
Thread::Backtrace::Location,
Thread::Backtrace::Location]
Thread::Backtrace::Location �Ƃ����N���X�ł��邱�Ƃ��킩��܂��DThread::Backtrace::Location.inspect ���C�Ӑ}�I�� String#inspect �̌��ʂƓ����\���������ɂȂ��Ă��邩��C�����悤�Ɍ������ł��ˁD
�i���C���Ȃ��� Ruby 2.0 �ł�
[#<Thread::Backtrace::Location:0x0000000159e920>, #<Thread::Backtrace::Location:0x0000000159e8f8>, #<Thread::Backtrace::Location:0x0000000159e8d0>, #<Thread::Backtrace::Location:0x0000000159e8a8>, #<Thread::Backtrace::Location:0x0000000159e880>]
�ƕ\���������āH�@���������āC�܂� Ruby 2.0.0 preview2 �����g������Ȃ���ł����I�H �i[ANN] ruby 2.0.0-preview2 released�j�j
�iinspect �̕ύX�� preview2 �����[�X���O�ɓ��ꂽ�̂ł����j
���āCThread::Backtrace::Location �͂������֗̕��ȃ��\�b�h�������Ă��܂��D�܂��Cto_s ���s���ƁCcaller �̕Ԃ�������Ɠ����\�L�ɂȂ�܂��D
���ɂ́C���̂悤�ȃ��\�b�h������܂��D
label �� base_label �Ɋւ��Ă͐������K�v�ł��傤�D
�Ⴆ�C�u���b�N�̒��� caller ���Ăяo���ƁC���̂悤�ɕ\������܂��D
1.times{
p caller(0)
}
#=> ["t.rb:3:in `block in <main>'", "t.rb:2:in `times'", "t.rb:2:in `<main>'"]
�g�b�v���x���Ȃ̂ŁC<main> �����\�b�h���ɂ����镔���łł����C�u���b�N�̒��Ŏ��s����Ă���̂ŁC`block in <main>' �Ƃ����\�L�������Ă���܂��D�����C�����ŗ~�����̂� <main> �����������肷��ƁC������킴�킴���K�\���Ő�o���̂͂���ǂ��̂ŁCbase_label �Ƃ���� <main> �̕����������o����C�Ƃ����悤�ɂ��Ă��܂��D
�ł́C���ۂɎ����Ă݂܂��傤�D
require 'pp'
def m1
1.times{
$locs = caller_locations
}
end
def m2; m1; end
class C
tap{
m2
}
end
$locs.each{|loc|
puts "path : #{loc.path}"
puts "absolute_path: #{loc.absolute_path}"
puts "lineno : #{loc.lineno}"
puts "label : #{loc.label}"
puts "base_label : #{loc.base_label}"
}
#=>
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 4
label : times
base_label : times
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 4
label : m1
base_label : m1
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 9
label : m2
base_label : m2
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 13
label : block in <class:C>
base_label : <class:C>
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 14
label : tap
base_label : tap
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 14
label : <class:C>
base_label : <class:C>
path : t.rb
absolute_path: c:/ko1/src/rb/t.rb
lineno : 11
label : <main>
base_label : <main>
��� �Љ�� ISeq#path �ȂƓ����悤�ȃC���^�[�t�F�[�X�ɂȂ��Ă���Ƃ����̂��킩��Ǝv���܂��D�Ƃ������C�����悤�ɂȂ�悤�ɍ��܂����D
�Ȃ��CThread#backtrace ���CThread::Backtrace::Location �̔z���Ԃ� Thread#backtrace_locations �Ƃ������\�b�h���lj�����Ă��܂��D
�ł́C�����͂���Ȋ����ŁD
�Ƃ����킯�ŁCRuby 2.0.0 preview2 ���o�܂����I�i[ANN] ruby 2.0.0-preview2 released�j�j
�F�����ĉ������D���͂��ĉ��������S�Ă̊F�l�Ɋ��Ӓv���܂��D
inspect�̌��ʂ�
[#<Thread::Backtrace::Location "t.rb", 7, "in `m2'">, ...]
�Ƃ��A
[#<["t.rb", 7, "in `m2'"]>, ...]
�Ƃ����悤�Ƀp�[�X���ꂽ���ʂ�������Ă����ق������ꂵ���Ȃ��Ǝv���܂����Bcaller_locations���g�������Ƃ��̓p�[�X���ꂽ���ʂ��~�����̂ŁA�ǂ��p�[�X���ꂽ�����킩�����ق����������ł��B to_s�̕���caller�Ɠ����ł悢�Ǝv���܂��B
�@ML �ł��܂��傤�Dticket ����ĖႦ�܂����H
Ruby VM advent calendar #1
���� 12 ���ł��ˁD�������̂ł��D �A�h�x���g�J�����_�[�Ƃ����̂����s���Ă��邻���Ȃ̂ŁC���[�e�N�i�菑���j�łȂ����Ă݂܂��D�l�^�� Ruby VM �ɊW���鉽���Ŗ��߂Ă݂܂��D
VM �Ƃ����� bytecode �ł����CRuby �� VM �Ńo�C�g�R�[�h��\������̂� RubyVM::InstructionSequence �N���X�̃I�u�W�F�N�g�ł��D�����̂� ISeq �Ƃ��܂��D
�������Cpreview2 �ɊԂɍ��킹�邽�߂ɋ}���� RubyVM::InstructionSequence.of(obj) �Ƃ������\�b�h�����܂����D�������邩�Ƃ����ƁCProc �� Method ������āCISeq ��Ԃ����\�b�h�ł��D
���ꂩ��CISeq#path �Ȃǂ����܂����DISeq ���ǂ̃t�@�C���ɂ��������C�Ƃ����̂�Ԃ��܂��D�ق��ɂ� variant ������܂����C�܂�����킩��܂���ˁD
���ꂪ����ƁC����ȃe�X�g�������܂��D
LINE_OF_HERE = __LINE__
def test_location
iseq = ISeq.of(method(:test_location))
assert_equal(__FILE__, iseq.path)
assert(/#{__FILE__}/ =~ iseq.absolute_path)
assert_equal("test_location", iseq.label)
assert_equal("test_location", iseq.base_label)
assert_equal(LINE_OF_HERE+1, iseq.first_lineno)
line = __LINE__
iseq = ISeq.of(Proc.new{})
assert_equal(__FILE__, iseq.path)
assert(/#{__FILE__}/ =~ iseq.absolute_path)
assert_equal("test_location", iseq.base_label)
assert_equal("block in test_location", iseq.label)
assert_equal(line+1, iseq.first_lineno)
end
���ꂩ��C���̂悤�ȃR�[�h�ŁC���ݑ��݂��� ISeq �����ׂďW�߂邱�Ƃ��ł��܂��D�ŏI�I�ɁC�t�@�C�������ƂɏW�v���C�s���Ń\�[�g�����`�ŏo�͂��Ă��܂��D
require 'pp'
h = Hash.new{|h, k| h[k] = []}
ObjectSpace.each_object(RubyVM::InstructionSequence){|iseq|
h[iseq.absolute_path || iseq.path] << iseq
}
h.each{|file, iseqs|
puts file
pp iseqs.map{|iseq| [iseq.first_lineno, iseq.label]}.sort
}
�����͂��̕ӂŁD
��������ɃA�h�x���g�J�����_�[�����Ⴂ���Ă���낤�ȁD
�R�����g��preview�ɂ��܂��ꂽ�̂ŁA������x���e���Ă݂�B
�����A�ȉ��̂悤�ɂ���K�v���[ ensure�łȂ�Ƃ�����悤�ɂ������ł��ˁB preview2�ł�
# -*- coding: utf-8 -*- require 'timeout' e=Class.new(Exception) Thread.async_interrupt_timing(e => :defer){ # �����ł͈�� Timeout::Error �͎��Ȃ��i���f���Ȃ��j begin timeout(30,e){ begin Thread.async_interrupt_timing(e => :immediate){ ... # ���� X�D�����ł� timeout �ɂ���Ē��f����� } ensure ... # ��n�������D�����ł͈�� timeout �͎��Ȃ��i���f���Ȃ��j end } Thread.async_interrupt_timing(e=>:immediate){} rescue e end }trunk(�o�O���Ă邩������Ȃ�)�ł�
# -*- coding: utf-8 -*- require 'timeout' e=Class.new(Exception) timeout(30,e){ begin Thread.async_interrupt_timing(e => :immediate){ ... # ���� X�D�����ł� timeout �ɂ���Ē��f����� } ensure Thread.async_interrupt_timing(e => :defer){ #blocking�ȏ��������ꍇ�ɕK�v ... # ��n�������D�����ł͈�� timeout �͎��Ȃ��i���f���Ȃ��j } end }�܂���
# -*- coding: utf-8 -*- require 'timeout' e=Class.new(Exception) timeout(30,e){ # preview2�ł͂�����timeout�ɂ���Ē��f�����\�������� Thread.async_interrupt_timing(e => :defer){ #previe2 or ensure��blocking�ȏ��������ꍇ�ɕK�v begin Thread.async_interrupt_timing(e => :immediate){ ... # ���� X�D�����ł� timeout �ɂ���Ē��f����� } ensure ... # ��n�������D�����ł͈�� timeout �͎��Ȃ��i���f���Ȃ��j end } } }��ԍŌ�̃R�[�h��preview2�ł�����������肭�������܂��B(�܂�R�����g�ŏ������ꏊ��������)
�@���R�������̂�Y��Ă܂����B�܂�Atimeout�̃u���b�N���Ŕ��������O��Timeout::Error�ł͂Ȃ�����ł��B