Tôi nghĩ rằng nhiều nhà phát triển Rails không hiểu đầy đủ về tính năng ghi nhớ và cách hoạt động của tính năng ghi nhớ. Tôi đã nhìn thấy nó áp dụng cho các phương thức trả về các bộ sưu tập được tải xuống lười biếng (như một bộ dữ liệu Sequel), hoặc áp dụng cho các phương thức không có đối số nhưng tính toán một cái gì đó dựa trên các biến mẫu. Trong trường hợp đầu tiên, việc ghi nhớ là không có gì ngoài chi phí, và trong lần thứ hai đó là một nguồn khó chịu và khó khăn để theo dõi lỗi.
tôi sẽ không áp dụng memoization nếu
- giá trị trả về là chỉ hơi đắt để tính toán. Nó sẽ phải là rất tốn kém và không thể tối ưu hóa được nữa, vì nó đáng để ghi nhớ.
- giá trị trả lại là hoặc có thể được tải chậm
- phương thức không phải là hàm thuần túy, tức là nó được đảm bảo trả về chính xác cùng một giá trị cho cùng một đối số - và chỉ sử dụng đối số để thực hiện công việc hoặc các chức năng thuần túy khác. Sử dụng các biến mẫu hoặc các phương thức gọi mà lần lượt sử dụng các biến mẫu có nghĩa là phương thức có thể trả về các kết quả khác nhau cho cùng một đối số.
Cũng có những trường hợp khác mà việc ghi nhớ không phù hợp, chẳng hạn như ghi nhớ và câu trả lời ở trên, nhưng đây là ba điều mà tôi cho là không rõ ràng.
Mục cuối cùng có lẽ là quan trọng nhất: memoization lưu trữ kết quả dựa trên những lập luận để phương pháp này, nếu phương pháp này trông như thế này nó không thể được memoized:
def unmemoizable1(name)
"%s was here %s" % name, Time.now.strftime('%Y-%m-%d')
end
def unmemoizable2
find_by_shoe_size(@size)
end
Cả hai có thể, tuy nhiên, được viết lại để tận dụng lợi thế của memoization (mặc dù trong hai trường hợp, những nó nên rõ ràng là không được thực hiện vì lý do khác):
def unmemoizable1(name)
memoizable1(name, Time.now.strftime('%Y-%m-%d'))
end
def memoizable1(name, time)
"#{name} was here #{time}"
end
memoize :memoizable1
def unmemoizable2
memoizable2(@size)
end
def memoizable2(size)
find_by_shoe_size(size)
end
memoize :memoizable2
(giả định rằng find_by_shoe_size
không có, hoặc dựa vào, bất kỳ tác dụng phụ)
Bí quyết là trích xuất một hàm thuần túy từ phương pháp và áp dụng ghi nhớ cho thay vào đó.
Khi bạn nói "nghĩa là nó được đảm bảo trả lại chính xác cùng một giá trị cho cùng một đối số", điều đó sẽ áp dụng như thế nào với các truy vấn Rails ActiveRecord? Ví dụ: tôi đã ghi nhớ phương thức tìm nạp tất cả các thành phố được đánh dấu là đang hoạt động trong mô hình Thành phố, ví dụ: '' 'def self.active @active_cities = || ("cities.active = (?)", true) kết thúc '' 'Khi thành phố mới được thêm vào cơ sở dữ liệu một cách thường xuyên bởi quản trị viên khi ứng dụng đang hoạt động, tôi có cần phải khởi động lại máy chủ để ghi đè biến mẫu được ghi nhớ này hay không ? Hay một biến mẫu ghi nhớ bị hủy và tái tạo sau mỗi yêu cầu? – Kelseydh
Để trả lời ở trên: Tôi nhận ra rằng * ghi nhớ chỉ tồn tại một biến mẫu trong vòng đời của ** một yêu cầu. *** Đây là điều làm tôi bối rối. Đối với người mới bắt đầu, tôi khuyên bạn nên thêm điểm quan trọng này vào định nghĩa của bạn. – Kelseydh