Hướng dẫn python in-memory cache - bộ đệm trong bộ nhớ python
Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Bộ đệm trong Python với LRU_CACHE This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Caching in Python With lru_cache Show
Có nhiều cách để đạt được các ứng dụng nhanh và đáp ứng. Bộ nhớ đệm là một cách tiếp cận, khi được sử dụng chính xác, làm cho mọi thứ nhanh hơn nhiều trong khi giảm tải cho tài nguyên điện toán. Mô -đun Python sườn 7 đi kèm với trình trang trí 8, cung cấp cho bạn khả năng lưu trữ kết quả của các chức năng của bạn bằng chiến lược ít được sử dụng gần đây (LRU) gần đây. Đây là một kỹ thuật đơn giản nhưng mạnh mẽ mà bạn có thể sử dụng để tận dụng sức mạnh của bộ đệm trong mã của bạn.Caching is one approach that, when used correctly, makes things much faster while decreasing the load
on computing resources. Python’s 7 module comes with the 8 decorator, which gives you the ability to cache the result of your functions using the Least Recently Used (LRU) strategy. This is a simple yet powerful technique that you can use to leverage the power of caching in your code.
Trong hướng dẫn này, bạn sẽ học:
Đến cuối hướng dẫn này, bạn sẽ có một sự hiểu biết sâu sắc hơn về cách thức hoạt động của bộ đệm và cách tận dụng nó trong Python. Bộ nhớ đệm và sử dụng của nóBộ nhớ đệm là một kỹ thuật tối ưu hóa mà bạn có thể sử dụng trong các ứng dụng của mình để giữ dữ liệu gần đây hoặc thường được sử dụng ở các vị trí bộ nhớ nhanh hơn hoặc tính toán rẻ hơn để truy cập so với nguồn của chúng. is an optimization technique that you can use in your applications to keep recent or often-used data in memory locations that are faster or computationally cheaper to access than their source. Hãy tưởng tượng bạn đang xây dựng một ứng dụng Readerer tin tức về những tin tức mới nhất từ các nguồn khác nhau. Khi người dùng điều hướng qua danh sách, ứng dụng của bạn tải xuống các bài viết và hiển thị chúng trên màn hình. Điều gì sẽ xảy ra nếu người dùng quyết định di chuyển nhiều lần qua lại giữa một vài bài báo tin tức? Trừ khi bạn đã lưu trữ dữ liệu, ứng dụng của bạn sẽ phải tìm nạp cùng một nội dung mỗi lần! Điều đó sẽ làm cho hệ thống người dùng của bạn chậm chạp và gây thêm áp lực lên máy chủ lưu trữ các bài viết. Một cách tiếp cận tốt hơn sẽ là lưu trữ nội dung cục bộ sau khi tìm nạp từng bài viết. Sau đó, lần tiếp theo người dùng quyết định mở một bài viết, ứng dụng của bạn có thể mở nội dung từ một bản sao lưu trữ cục bộ thay vì quay lại nguồn. Trong khoa học máy tính, kỹ thuật này được gọi là bộ nhớ đệm.caching. Thực hiện bộ nhớ cache bằng từ điển PythonBạn có thể thực hiện một giải pháp bộ đệm trong Python bằng cách sử dụng từ điển. Ở lại với ví dụ NewsReader, thay vì truy cập trực tiếp đến máy chủ mỗi khi bạn cần tải xuống một bài viết, bạn có thể kiểm tra xem bạn có nội dung trong bộ nhớ cache của mình không và quay lại máy chủ nếu bạn không có. Bạn có thể sử dụng URL bài viết làm khóa và nội dung của nó làm giá trị. Ở đây, một ví dụ về cách kỹ thuật bộ đệm này có thể trông:
Lưu mã này vào tệp 1, cài đặt thư viện 2, sau đó chạy tập lệnh:
Lưu ý cách bạn nhận được chuỗi 3 được in một lần mặc dù đã gọi 4 hai lần, trong dòng 17 và 18. Điều này xảy ra bởi vì, sau khi truy cập bài viết lần đầu tiên, bạn đặt URL và nội dung của nó vào từ điển 5. Lần thứ hai, mã không cần phải lấy lại mục từ máy chủ.Chiến lược bộ nhớ đệmCó một vấn đề lớn với việc triển khai bộ đệm này: Nội dung của từ điển sẽ phát triển vô thời hạn! Khi người dùng tải xuống nhiều bài viết hơn, ứng dụng sẽ tiếp tục lưu trữ chúng trong bộ nhớ, cuối cùng khiến ứng dụng bị sập. Để giải quyết vấn đề này, bạn cần một chiến lược để quyết định bài viết nào nên ở trong bộ nhớ và nên loại bỏ. Các chiến lược lưu trữ này là các thuật toán tập trung vào việc quản lý thông tin được lưu trữ và chọn các mục nào để loại bỏ để nhường chỗ cho các mục mới. Có một số chiến lược khác nhau mà bạn có thể sử dụng để trục xuất các mục từ bộ đệm và giữ cho nó không phát triển quá khứ từ kích thước tối đa của nó. Dưới đây là năm trong số những người phổ biến nhất, với lời giải thích khi mỗi người hữu ích nhất:
Trong các phần dưới đây, bạn sẽ xem xét kỹ hơn về chiến lược LRU và cách thực hiện nó bằng cách sử dụng nhà trang trí 8 từ mô -đun Python tựa 7.Lặn vào chiến lược bộ đệm ít được sử dụng gần đây nhất (LRU)Một bộ đệm được triển khai bằng chiến lược LRU tổ chức các mục của nó theo thứ tự sử dụng. Mỗi khi bạn truy cập một mục nhập, thuật toán LRU sẽ di chuyển nó lên đầu bộ đệm. Bằng cách này, thuật toán có thể nhanh chóng xác định mục nhập mà Lừa không sử dụng lâu nhất bằng cách nhìn vào dưới cùng của danh sách. Hình sau đây cho thấy biểu diễn bộ đệm giả thuyết sau khi người dùng của bạn yêu cầu một bài viết từ mạng: Lưu ý cách bộ đệm lưu trữ bài viết trong vị trí gần đây nhất trước khi phục vụ nó cho người dùng. Hình sau đây cho thấy những gì xảy ra khi người dùng yêu cầu bài viết thứ hai: Bài viết thứ hai lấy vị trí gần đây nhất, đẩy bài viết đầu tiên xuống danh sách. Chiến lược LRU giả định rằng gần đây một đối tượng đã được sử dụng, càng có nhiều khả năng cần thiết trong tương lai, vì vậy nó cố gắng giữ đối tượng đó trong bộ đệm trong thời gian dài nhất. Nhìn trộm phía sau hậu trường của bộ đệm LRUMột cách để thực hiện bộ đệm LRU trong Python là sử dụng kết hợp danh sách được liên kết gấp đôi và bản đồ băm. Yếu tố đầu của danh sách được liên kết gấp đôi sẽ chỉ ra mục nhập được sử dụng gần đây nhất và đuôi sẽ chỉ ra mục nhập ít gần đây nhất.head element of the doubly linked list would point to the most recently used entry, and the tail would point to the least recently used entry. Hình dưới đây cho thấy cấu trúc tiềm năng của việc triển khai bộ đệm LRU đằng sau hậu trường: Sử dụng bản đồ băm, bạn có thể đảm bảo quyền truy cập vào mọi mục trong bộ đệm bằng cách ánh xạ từng mục vào vị trí cụ thể trong danh sách được liên kết gấp đôi. Chiến lược này rất nhanh. Truy cập mục ít nhất được sử dụng gần đây và cập nhật bộ đệm là các hoạt động với thời gian chạy O (1). Kể từ phiên bản 3.2, Python đã bao gồm nhà trang trí 8 để thực hiện chiến lược LRU. Bạn có thể sử dụng trình trang trí này để bọc các chức năng và lưu trữ kết quả của chúng lên đến số lượng mục tối đa.Sử dụng @lru_cache để thực hiện bộ đệm LRU trong PythonGiống như giải pháp bộ đệm mà bạn đã triển khai trước đó, 8 sử dụng từ điển đằng sau hậu trường. Nó lưu trữ kết quả của chức năng dưới một khóa bao gồm cuộc gọi đến hàm, bao gồm các đối số được cung cấp. Điều này rất quan trọng bởi vì nó có nghĩa là những lập luận này phải được băm cho người trang trí hoạt động.hashable for the decorator to work.Chơi với cầu thangHãy tưởng tượng bạn muốn xác định tất cả các cách khác nhau mà bạn có thể đến một cầu thang cụ thể trong cầu thang bằng cách nhảy một, hai hoặc ba cầu thang cùng một lúc. Có bao nhiêu con đường đến cầu thang thứ tư? Dưới đây là tất cả các kết hợp khác nhau: Bạn có thể đóng khung một giải pháp cho vấn đề này bằng cách tuyên bố rằng, để đến cầu thang hiện tại của bạn, bạn có thể nhảy từ một cầu thang, hai cầu thang hoặc ba cầu thang bên dưới. Thêm số lượng kết hợp nhảy bạn có thể sử dụng để đạt được từng điểm đó sẽ cung cấp cho bạn tổng số cách có thể để đạt được vị trí hiện tại của bạn. Ví dụ: số lượng kết hợp để đạt được cầu thang thứ tư sẽ bằng tổng số các cách khác nhau mà bạn có thể đạt được cầu thang thứ ba, thứ hai và thứ nhất: Như thể hiện trong hình, có bảy cách khác nhau để đến cầu thang thứ tư. Lưu ý cách giải pháp cho một cầu thang nhất định dựa trên các câu trả lời cho các vấn đề nhỏ hơn. Trong trường hợp này, để xác định các đường dẫn khác nhau đến cầu thang thứ tư, bạn có thể thêm bốn cách đến cầu thang thứ ba, hai cách đến cầu thang thứ hai và một cách đến cầu thang thứ nhất. Cách tiếp cận này được gọi là đệ quy. Nếu bạn muốn tìm hiểu thêm, thì hãy kiểm tra suy nghĩ đệ quy trong Python để giới thiệu về chủ đề này.recursion. If you want to learn more, then check out Thinking Recursively in Python for an introduction to the topic. Ở đây, một chức năng thực hiện đệ quy này:
Lưu mã này vào một tệp có tên 0 và chạy nó bằng lệnh sau:Tuyệt quá! Mã này hoạt động cho 1 cầu thang, nhưng làm thế nào về việc đếm có bao nhiêu bước để đến một vị trí cao hơn trong cầu thang? Thay đổi số cầu thang trong dòng 33 thành 2 và chạy lại tập lệnh:
Wow, hơn 53 triệu kết hợp! Đó là rất nhiều hoa bia! Thời gian mã của bạnKhi tìm ra giải pháp cho cầu thang thứ ba mươi, kịch bản này mất khá nhiều thời gian để hoàn thành. Để có được một đường cơ sở, bạn có thể đo được thời gian để mã chạy. Để thực hiện điều này, bạn có thể sử dụng mô -đun Python từ ____33. Thêm các dòng sau sau dòng 33:
Bạn cũng cần nhập mô -đun 3 ở đầu mã:
Ở đây, một lời giải thích từng dòng về các bổ sung này:
Bây giờ chạy lại tập lệnh:
Số giây bạn sẽ thấy phụ thuộc vào phần cứng cụ thể của bạn. Trên hệ thống của tôi, kịch bản mất bốn mươi giây, khá chậm cho chỉ ba mươi cầu thang! Một giải pháp mất nhiều thời gian này là một vấn đề, nhưng bạn có thể cải thiện nó bằng cách sử dụng ghi nhớ. Sử dụng ghi nhớ để cải thiện giải phápViệc thực hiện đệ quy này giải quyết vấn đề bằng cách chia nó thành các bước nhỏ hơn xây dựng lẫn nhau. Hình sau đây cho thấy một cây trong đó mọi nút đại diện cho một cuộc gọi cụ thể đến 5:Lưu ý cách bạn cần gọi 5 với cùng một đối số nhiều lần. Ví dụ, 2 được tính toán hai lần, 3 được tính toán bốn lần, 4 bảy lần và 5 sáu lần. Gọi cùng một chức năng nhiều lần thêm các chu kỳ tính toán mà aren cần thiết, kết quả sẽ luôn giống nhau.Để khắc phục vấn đề này, bạn có thể sử dụng một kỹ thuật gọi là ghi nhớ. Cách tiếp cận này đảm bảo rằng một hàm không chạy cho cùng một đầu vào nhiều lần bằng cách lưu trữ kết quả của nó vào bộ nhớ và sau đó tham chiếu nó sau khi cần thiết. Kịch bản này nghe có vẻ là cơ hội hoàn hảo để sử dụng Python từ 8 Trang trí!memoization. This approach ensures that a function doesn’t run for the same inputs more than once by storing its result in memory and then referencing it later when necessary. This scenario sounds like the perfect opportunity to use Python’s 8 decorator!Chỉ với hai thay đổi, bạn có thể cải thiện đáng kể thời gian chạy thuật toán:
Dưới đây, phần đầu của tập lệnh sẽ trông như thế nào với hai bản cập nhật:
Chạy tập lệnh được cập nhật tạo ra kết quả sau:
Bộ nhớ đệm kết quả của chức năng mất thời gian chạy từ 40 giây xuống còn 0,0008 mili giây! Đó là một cải tiến tuyệt vời! Hãy nhớ rằng, đằng sau hậu trường, người trang trí 8 lưu trữ kết quả của 5 cho mỗi đầu vào khác nhau. Mỗi khi mã gọi hàm với cùng một tham số, thay vì tính toán một câu trả lời một lần nữa, nó sẽ trả về kết quả chính xác trực tiếp từ bộ nhớ. Điều này giải thích sự cải thiện lớn về hiệu suất khi sử dụng 8.Giải nén chức năng của @lru_cacheVới bộ trang trí 8 tại chỗ, bạn lưu trữ mọi cuộc gọi và trả lời trong bộ nhớ để truy cập sau nếu được yêu cầu lại. Nhưng bạn có thể lưu bao nhiêu cuộc gọi trước khi hết bộ nhớ?Nhà trang trí Python từ 8 cung cấp thuộc tính 6 xác định số lượng mục tối đa trước khi bộ đệm bắt đầu đuổi các mặt hàng cũ. Theo mặc định, 6 được đặt thành 8. Nếu bạn đặt 6 thành 0, thì bộ đệm sẽ phát triển vô thời hạn và không có mục nào sẽ bị trục xuất. Điều này có thể trở thành một vấn đề nếu bạn lưu trữ một số lượng lớn các cuộc gọi khác nhau trong bộ nhớ.Ở đây, một ví dụ về 8 bằng cách sử dụng thuộc tính 6:
Trong trường hợp này, bạn đã giới hạn bộ đệm đến tối đa các mục 3. Khi một cuộc gọi mới xuất hiện, việc triển khai trang trí của nhà trang trí sẽ trục xuất ít nhất được sử dụng gần đây của các mục 3 hiện có để tạo một vị trí cho mặt hàng mới.Để xem điều gì xảy ra với sự bổ sung mới này vào mã này, bạn có thể sử dụng 5, được cung cấp bởi 8, để kiểm tra số lần truy cập và bỏ lỡ và kích thước hiện tại của bộ đệm. Để rõ ràng, hãy xóa mã thời gian chạy của hàm. Ở đây, cách mà tập lệnh cuối cùng chăm sóc tất cả các sửa đổi:hits and misses and the current size of the cache. For clarity, remove the code that times the runtime of the function. Here’s how the final script looks after all the modifications: 0Nếu bạn gọi lại tập lệnh, thì bạn sẽ thấy kết quả sau: 1Bạn có thể sử dụng thông tin được trả về bởi 5 để hiểu cách thức hoạt động của bộ đệm và tinh chỉnh nó để tìm sự cân bằng phù hợp giữa tốc độ và lưu trữ.
Ở đây, một sự cố của các thuộc tính được cung cấp bởi 5:
Nếu bạn cần xóa tất cả các mục từ bộ đệm, thì bạn có thể sử dụng 5 được cung cấp bởi 8.Thêm hết hạn bộ nhớ cacheHãy tưởng tượng bạn muốn phát triển một kịch bản theo dõi Python thực và in số lượng ký tự trong bất kỳ bài viết nào có chứa từ 7.Real Python cung cấp một nguồn cấp dữ liệu nguyên tử, vì vậy bạn có thể sử dụng thư viện ____78 để phân tích thức ăn và thư viện 2 để tải nội dung của bài viết như bạn đã làm trước đây.Ở đây, một triển khai của tập lệnh Monitor: 2Lưu tập lệnh này vào một tệp có tên 0, cài đặt thư viện 8 và 2 và chạy tập lệnh. Nó sẽ chạy liên tục cho đến khi bạn dừng nó bằng cách nhấn Ctrl+C trong cửa sổ đầu cuối của bạn:Ctrl+C in your terminal window: 3Ở đây, một lời giải thích từng bước về mã:
Mỗi khi tập lệnh tải một bài viết, thông báo 3 được in vào bảng điều khiển. Nếu bạn để tập lệnh chạy đủ lâu, thì bạn sẽ thấy cách tin nhắn này xuất hiện nhiều lần, ngay cả khi tải cùng một liên kết.Đây là một cơ hội tuyệt vời để lưu trữ nội dung của bài viết và tránh truy cập mạng cứ sau năm giây. Bạn có thể sử dụng trình trang trí 8, nhưng điều gì xảy ra nếu nội dung của bài viết được cập nhật?Lần đầu tiên bạn truy cập bài viết, người trang trí sẽ lưu trữ nội dung của nó và trả về cùng một dữ liệu mỗi lần sau đó. Nếu bài đăng được cập nhật, thì tập lệnh màn hình sẽ không bao giờ nhận ra nó vì nó sẽ kéo bản sao cũ được lưu trữ trong bộ đệm. Để giải quyết vấn đề này, bạn có thể đặt các mục lưu trữ bộ nhớ cache của mình để hết hạn. Kỷ niệm các mục lưu trữ dựa trên cả thời gian và không gianNhà trang trí 8 chỉ đuổi các mục hiện có khi có thêm không gian để lưu trữ danh sách mới. Với đủ không gian, các mục trong bộ đệm sẽ sống mãi mãi và không bao giờ được làm mới.Điều này trình bày một vấn đề cho tập lệnh giám sát của bạn vì bạn sẽ không bao giờ tìm nạp các bản cập nhật được xuất bản cho các bài viết được lưu trong bộ nhớ cache trước đó. Để giải quyết vấn đề này, bạn có thể cập nhật triển khai bộ đệm để hết hạn sau một thời gian cụ thể. Bạn có thể thực hiện ý tưởng này thành một nhà trang trí mới mở rộng 8. Nếu người gọi cố gắng truy cập vào một mục mà qua đời, thì bộ đệm đã giành được nội dung của nó, buộc người gọi phải lấy bài viết từ mạng.Ở đây, một triển khai có thể của người trang trí mới này: 4Ở đây, một sự cố của việc thực hiện này:
Lưu ý làm thế nào, khi một mục nhập hết hạn, bộ trang trí này sẽ xóa toàn bộ bộ đệm liên quan đến chức năng. Trọn đời áp dụng cho toàn bộ bộ đệm, không phải cho các bài viết riêng lẻ. Một triển khai tinh vi hơn của chiến lược này sẽ đuổi các mục dựa trên cuộc sống cá nhân của họ. Bộ nhớ đệm bài viết với người trang trí mớiBây giờ bạn có thể sử dụng trình trang trí 4 mới của mình với tập lệnh 8 để ngăn chặn nội dung của một bài viết mỗi khi bạn truy cập nó.Đặt mã với nhau trong một tập lệnh duy nhất để đơn giản, bạn kết thúc với các mục sau: 5Lưu ý cách dòng 30 trang trí 9 với 4 và chỉ định tính hợp lệ của 9 giây. Bất kỳ nỗ lực nào để truy cập cùng một bài viết từ máy chủ trong vòng 9 giây sau khi lấy được, nó sẽ trả về nội dung từ bộ đệm và không bao giờ nhấn vào mạng.Chạy tập lệnh và xem kết quả: 6Lưu ý cách mã in thông báo 3 lần đầu tiên truy cập các bài viết phù hợp. Sau đó, tùy thuộc vào tốc độ mạng và sức mạnh tính toán của bạn, tập lệnh sẽ lấy các bài viết từ bộ đệm một hoặc hai lần trước khi nhấn lại máy chủ.Kịch bản cố gắng truy cập các bài viết cứ sau 6 giây và bộ nhớ cache hết hạn cứ sau mỗi 9 giây. Những thời điểm này có lẽ quá ngắn cho một ứng dụng thực sự, vì vậy bạn có thể có được một cải tiến đáng kể bằng cách điều chỉnh các cấu hình này.Sự kết luậnBộ nhớ đệm là một kỹ thuật tối ưu hóa thiết yếu để cải thiện hiệu suất của bất kỳ hệ thống phần mềm nào. Hiểu cách thức hoạt động của bộ nhớ đệm là một bước cơ bản để kết hợp nó một cách hiệu quả trong các ứng dụng của bạn. Trong hướng dẫn này, bạn đã học được:
Bước tiếp theo để thực hiện các chiến lược bộ đệm khác nhau trong các ứng dụng của bạn là xem xét mô -đun ____10109. Thư viện này cung cấp một số bộ sưu tập và trang trí bao gồm một số chiến lược bộ đệm phổ biến nhất mà bạn có thể bắt đầu sử dụng ngay lập tức. Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Bộ đệm trong Python với LRU_CACHE This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Caching in Python With lru_cache |