什麼是 frozen_string_literal?

by Aaron • 10/23/2024, 1:11:32 PM

在使用 RUBOCOP 會發現儲存的時候 會在當前檔案最上方加一個 Magic Comment, # frozen_string_literal: true, 到底這個 comment 有什麼作用呢?

加上 frozen_string_literal: true/false 會有什麼差異 ?

其實就只是 string.freeze 的語法糖而已, 加上之後整個檔案的 string 就會變成 freeze 的狀態

# frozen_string_literal: true

str = "Hello World"
str[1] = "h"
pp str

# Traceback (most recent call last):
#         1: from test.rb:14:in `<main>'
# test.rb:14:in `[]=': can't modify frozen String: "Hello World" (FrozenError)

相當於

str = "Hello World".freeze
str[1] = "h"
pp str

為什麼要 freeze sting 呢? 什麼時候應該要加 frozen_string_literal: true ?

  1. 可以減少 Garbage
start = GC.stat[:total_allocated_objects]
100_000.times { "test".freeze.dup }
finish = GC.stat[:total_allocated_objects]

puts "With frozen: #{finish - start}"
# With frozen: 100001

start = GC.stat[:total_allocated_objects]
100_000.times { "test".dup }
finish = GC.stat[:total_allocated_objects]

puts "Without frozen: #{finish - start}"
# Without frozen: 200001
  1. 這樣在當前的作用域 string 的行為會跟 symbol 接近
# frozen_string_literal: true

foo = "aaron"
bar = "aaron"

pp foo.object_id
# 60
pp bar.object_id
# 60

Benchmark.bm(15) do |x|
  x.report("Without frozen: ") do
    1_000_000_000.times { "aaron".dup }
  end
  x.report("With frozen") do
    1_000_000_000.times {"aaron".freeze.dup}
  end
end
#                       user     system      total        real
# Without frozen: 108.935660   3.775396 112.711056 (113.095394)
# With frozen      90.101091   1.988797  92.089888 ( 92.543350)

References

© 2025 Aaron Li. All Rights Reserved.