Несмотря на то, что Ruby широко считается интерпретируемым языком, Ruby частично компилируется в большинстве распространенных реализаций языка. Стандартный интерпретатор (YARV) сначала компилирует ваш исходный код в байт-код, а затем интерпретирует этот байт-код. (Если вы хотите go более подробно об этом топи c, я настоятельно рекомендую Ruby под микроскопом ).
Вы можете использовать RubyVM::InstructionSequence
чтобы увидеть байт-код, сгенерированный для определенного Ruby кода. Давайте сравним байт-код для ваших двух примеров:
irb(main):002:0> puts RubyVM::InstructionSequence.compile("print('Message')").dis
asm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,16)> (catch: FALSE)
0000 putself ( 1)[Li]
0001 putstring "Message"
0003 opt_send_without_block <callinfo!mid:print, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0006 leave
=> nil
irb(main):003:0> puts RubyVM::InstructionSequence.compile("message = 'Message'; print(message)").disasm
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,35)> (catch: FALSE)
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] message@0
0000 putstring "Message" ( 1)[Li]
0002 setlocal_WC_0 message@0
0004 putself
0005 getlocal_WC_0 message@0
0007 opt_send_without_block <callinfo!mid:print, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
0010 leave
=> nil
Как мы можем видеть здесь, print('Message')
имеет меньше инструкций байт-кода, поэтому, вероятно, будет очень немного быстрее (не достаточно быстрее, чтобы жертвовать ясностью при написании кода). Кроме того, print('Message')
не использует локальные переменные, поэтому для этого фрагмента не требуется таблица локальных переменных.
В вашем примере message = 'Message'; print(message)
имеется больше инструкций с байт-кодом, поскольку для него требуется установить и получить локальную переменную и впоследствии также требуется таблица локальных переменных (показана как local table (size: 1, ...)
). Это означает, что это займет немного больше памяти.
Несмотря на два разных подхода, вы все равно создаете один и тот же объект - строку 'Message'
. Из-за этого на сборщик мусора мало влияет, как мы можем видеть из значения GC.stat
: (a.rb не использует local, а b.rb -)
$ ruby a.rb
Message{:count=>12, :heap_allocated_pages=>51, :heap_sorted_length=>62, :heap_allocatable_pages=>11, :heap_available_slots=>20791, :heap_live_slots=>20530, :heap_free_slots=>261, :heap_final_slots=>0, :heap_marked_slots=>15224, :heap_eden_pages=>51, :heap_tomb_pages=>0, :total_allocated_pages=>51, :total_freed_pages=>0, :total_allocated_objects=>68286, :total_freed_objects=>47756, :malloc_increase_bytes=>374152, :malloc_increase_bytes_limit=>16777216, :minor_gc_count=>9, :major_gc_count=>3, :remembered_wb_unprotected_objects=>213, :remembered_wb_unprotected_objects_limit=>424, :old_objects=>14957, :old_objects_limit=>29920, :oldmalloc_increase_bytes=>431824, :oldmalloc_increase_bytes_limit=>16777216}%
$ ruby b.rb
Message{:count=>12, :heap_allocated_pages=>51, :heap_sorted_length=>62, :heap_allocatable_pages=>11, :heap_available_slots=>20785, :heap_live_slots=>20518, :heap_free_slots=>267, :heap_final_slots=>0, :heap_marked_slots=>15209, :heap_eden_pages=>51, :heap_tomb_pages=>0, :total_allocated_pages=>51, :total_freed_pages=>0, :total_allocated_objects=>68288, :total_freed_objects=>47770, :malloc_increase_bytes=>374488, :malloc_increase_bytes_limit=>16777216, :minor_gc_count=>9, :major_gc_count=>3, :remembered_wb_unprotected_objects=>213, :remembered_wb_unprotected_objects_limit=>424, :old_objects=>14956, :old_objects_limit=>29918, :oldmalloc_increase_bytes=>434104, :oldmalloc_increase_bytes_limit=>16777216}
The * Клавиша 1024 * показывает количество раз, которое запускался сборщик мусора, и он одинаков для обоих ваших примеров, поэтому он не влияет на сборку мусора.