Mô-đun gc python là gì?
Thông thường, bạn không cần phải lo lắng về việc quản lý bộ nhớ. Khi các đối tượng không còn cần thiết, Python sẽ tự động lấy lại bộ nhớ từ chúng. Tuy nhiên, hiểu cách thức hoạt động của GC có thể giúp bạn viết các chương trình Python tốt hơn và nhanh hơn Show
Quản lý bộ nhớKhông giống như nhiều ngôn ngữ khác, Python không nhất thiết phải giải phóng bộ nhớ trở lại Hệ điều hành. Thay vào đó, nó có một bộ cấp phát đối tượng chuyên dụng cho các đối tượng nhỏ hơn 512 byte, giữ lại một số khối bộ nhớ đã được cấp phát để sử dụng thêm trong tương lai. Dung lượng bộ nhớ mà Python nắm giữ tùy thuộc vào kiểu sử dụng. Trong một số trường hợp, tất cả bộ nhớ được phân bổ chỉ có thể được giải phóng khi quá trình Python kết thúc Nếu một quy trình Python chạy dài chiếm nhiều bộ nhớ hơn theo thời gian, điều đó không nhất thiết có nghĩa là bạn bị rò rỉ bộ nhớ. Nếu bạn quan tâm đến mô hình bộ nhớ của Python, bạn có thể đọc bài viết của tôi về quản lý bộ nhớ Vì hầu hết các đối tượng đều nhỏ nên bộ cấp phát bộ nhớ tùy chỉnh tiết kiệm rất nhiều thời gian cho việc cấp phát bộ nhớ. Ngay cả những chương trình đơn giản nhập thư viện của bên thứ ba cũng có thể phân bổ hàng triệu đối tượng trong suốt thời gian tồn tại của chương trình Thuật toán thu gom rácTrong Python, mọi thứ đều là đối tượng. số nguyên chẵn. Biết khi nào nên phân bổ chúng thật dễ dàng. Python làm điều đó khi bạn cần tạo một đối tượng mới. Không giống như phân bổ, phân bổ tự động rất phức tạp. Python cần biết khi nào đối tượng của bạn không còn cần thiết. Loại bỏ các đối tượng sớm sẽ dẫn đến sự cố chương trình Các thuật toán thu gom rác theo dõi những đối tượng nào có thể được phân bổ và chọn thời điểm tối ưu để phân bổ chúng. Trình thu gom rác tiêu chuẩn của CPython có hai thành phần, trình thu gom đếm tham chiếu và trình thu gom rác thế hệ, được gọi là mô-đun gc Thuật toán đếm tham chiếu cực kỳ hiệu quả và đơn giản, nhưng nó không thể phát hiện các chu kỳ tham chiếu. Đó là lý do tại sao Python có một thuật toán bổ sung được gọi là GC tuần hoàn thế hệ. Nó chỉ xử lý các chu kỳ tham chiếu Mô-đun đếm tham chiếu là cơ bản của Python và không thể tắt được, trong khi GC tuần hoàn là tùy chọn và có thể được kích hoạt theo cách thủ công đếm tham chiếuĐếm tham chiếu là một kỹ thuật đơn giản trong đó các đối tượng được giải phóng khi không có tham chiếu đến chúng trong chương trình Mỗi biến trong Python là một tham chiếu (con trỏ) đến một đối tượng chứ không phải giá trị thực. Ví dụ, câu lệnh gán chỉ cần thêm một tham chiếu mới vào vế phải. Một đối tượng có thể có nhiều tham chiếu (tên biến) Mã này tạo hai tham chiếu đến một đối tượng
Bản thân câu lệnh gán (mọi thứ ở bên trái) không bao giờ sao chép hoặc tạo dữ liệu mới Để theo dõi các tham chiếu, mọi đối tượng (kể cả số nguyên) đều có một trường bổ sung được gọi là số tham chiếu được tăng hoặc giảm khi một con trỏ tới đối tượng được tạo hoặc xóa. Xem phần, để được giải thích chi tiết Ví dụ, trong đó số lượng tham chiếu tăng
Nếu trường đếm tham chiếu về 0, CPython sẽ tự động gọi hàm giải phóng bộ nhớ dành riêng cho đối tượng. Nếu một đối tượng chứa các tham chiếu đến các đối tượng khác, thì số lượng tham chiếu của chúng cũng tự động giảm đi. Do đó, các đối tượng khác có thể được giải phóng lần lượt. Ví dụ: khi một danh sách bị xóa, số lượng tham chiếu cho tất cả các mục của danh sách đó sẽ giảm. Nếu một biến khác tham chiếu đến một mục trong danh sách, thì mục đó sẽ không bị hủy cấp phát Các biến, được khai báo bên ngoài hàm, lớp và khối, được gọi là toàn cầu. Thông thường, các biến như vậy tồn tại cho đến khi kết thúc quá trình của Python. Do đó, số lượng tham chiếu của các đối tượng, được tham chiếu bởi các biến toàn cục, không bao giờ giảm xuống 0. Để giữ cho chúng tồn tại, tất cả các hình cầu được lưu trữ bên trong một từ điển. Bạn có thể lấy nó bằng cách gọi hàm Các biến, được định nghĩa bên trong các khối (e. g. , trong một hàm hoặc lớp) có phạm vi cục bộ (i. e. , chúng là cục bộ trong khối của nó). Khi trình thông dịch Python thoát khỏi một khối, nó sẽ hủy các biến cục bộ và các tham chiếu của chúng đã được tạo bên trong khối. Nói cách khác, nó chỉ phá hủy tên Điều quan trọng là phải hiểu rằng cho đến khi chương trình của bạn ở trong một khối, trình thông dịch Python giả định rằng tất cả các biến bên trong nó đang được sử dụng. Để xóa thứ gì đó khỏi bộ nhớ, bạn cần gán giá trị mới cho biến hoặc thoát khỏi khối mã. Trong Python, khối mã phổ biến nhất là một hàm; . Đó là một lý do khác để giữ cho các chức năng nhỏ và đơn giản Bạn luôn có thể kiểm tra số lượng tài liệu tham khảo hiện tại bằng hàm Đây là một ví dụ đơn giản
Trong ví dụ trên, bạn có thể thấy rằng các tham chiếu hàm bị hủy sau khi Python thoát khỏi nó Đôi khi bạn cần loại bỏ sớm một biến toàn cục hoặc biến cục bộ. Để làm như vậy, bạn có thể sử dụng câu lệnh Lý do chính tại sao CPython sử dụng đếm tham chiếu là lịch sử. Ngày nay có rất nhiều cuộc tranh luận về những điểm yếu của một kỹ thuật như vậy. Một số người cho rằng các thuật toán thu gom rác hiện đại có thể hiệu quả hơn mà không cần đếm tham chiếu. Thuật toán đếm tham chiếu có rất nhiều vấn đề, chẳng hạn như tham chiếu vòng tròn, khóa luồng, chi phí hoạt động và bộ nhớ. Đếm tham chiếu là một trong những lý do tại sao Python không thể thoát khỏi GIL Ưu điểm chính của cách tiếp cận này là các đối tượng có thể bị hủy ngay lập tức và dễ dàng sau khi chúng không còn cần thiết nữa. Người thu gom rác thế hệTại sao chúng ta cần thêm bộ thu gom rác khi chúng ta đếm tham chiếu? Thật không may, đếm tham chiếu cổ điển có một vấn đề cơ bản - nó không thể phát hiện các chu kỳ tham chiếu. Một chu kỳ tham chiếu xảy ra khi một hoặc nhiều đối tượng đang tham chiếu lẫn nhau Đây là hai ví dụ. Như chúng ta có thể thấy, đối tượng 'lst' đang trỏ đến chính nó, hơn nữa, Để hiểu rõ hơn, bạn có thể chơi với một ví dụ Python đơn giản
Trong ví dụ trên, câu lệnh Để giải quyết vấn đề này, thuật toán phát hiện chu kỳ bổ sung đã được giới thiệu trong Python 1. 5. Mô-đun gc chịu trách nhiệm cho việc này và chỉ tồn tại để xử lý sự cố như vậy Các chu kỳ tham chiếu chỉ có thể xảy ra trong các đối tượng chứa (i. e. , trong các đối tượng có thể chứa các đối tượng khác), chẳng hạn như danh sách, từ điển, lớp, bộ dữ liệu. Thuật toán thu gom rác không theo dõi tất cả các loại bất biến ngoại trừ một bộ. Bộ dữ liệu và từ điển chỉ chứa các đối tượng bất biến cũng có thể không được theo dõi tùy thuộc vào các điều kiện nhất định. Do đó, kỹ thuật đếm tham chiếu xử lý tất cả các tham chiếu không tuần hoàn Khi nào kích hoạt GC thế hệKhông giống như đếm tham chiếu, GC tuần hoàn không hoạt động trong thời gian thực và chạy định kỳ. Để giảm tần suất của các cuộc gọi GC và tạm dừng vi mô, CPython sử dụng nhiều phương pháp phỏng đoán khác nhau GC phân loại các đối tượng vùng chứa thành ba thế hệ. Mỗi đối tượng mới bắt đầu trong thế hệ đầu tiên. Nếu một đối tượng tồn tại trong vòng thu gom rác, nó sẽ chuyển sang thế hệ cũ hơn (cao hơn). Các thế hệ thấp hơn được thu thập thường xuyên hơn các thế hệ cao hơn. Bởi vì hầu hết các đối tượng mới được tạo đều chết trẻ, nó cải thiện hiệu suất của GC và giảm thời gian tạm dừng của GC Để quyết định thời điểm chạy, mỗi thế hệ có một bộ đếm và ngưỡng riêng. Bộ đếm lưu trữ số lượng phân bổ đối tượng trừ đi các phân bổ kể từ lần thu thập cuối cùng. Mỗi khi bạn phân bổ một đối tượng vùng chứa mới, CPython sẽ kiểm tra bất cứ khi nào bộ đếm của thế hệ đầu tiên vượt quá giá trị ngưỡng. Nếu vậy, Python bắt đầu quá trình thu thập Nếu chúng tôi có hai hoặc nhiều thế hệ hiện vượt quá ngưỡng, thì GC sẽ chọn thế hệ cũ nhất. Đó là bởi vì các thế hệ già nhất cũng đang thu thập tất cả các thế hệ trước (trẻ hơn). Để giảm sự suy giảm hiệu suất cho các đối tượng tồn tại lâu dài, thế hệ thứ ba phải được chọn Các giá trị ngưỡng tiêu chuẩn được đặt tương ứng thành (700, 10, 10), nhưng bạn luôn có thể kiểm tra chúng bằng cách sử dụng hàm 1. Bạn cũng có thể điều chỉnh chúng cho khối lượng công việc cụ thể của mình bằng cách sử dụng hàm 2Cách tìm chu kỳ tham chiếuThật khó để giải thích thuật toán phát hiện chu kỳ tham chiếu trong một vài đoạn. Về cơ bản, GC lặp lại từng đối tượng vùng chứa và tạm thời loại bỏ tất cả các tham chiếu đến tất cả các đối tượng vùng chứa mà nó tham chiếu. Sau khi lặp lại đầy đủ, tất cả các đối tượng có số tham chiếu thấp hơn hai đều không thể truy cập được từ mã của Python và do đó có thể được thu thập Để hiểu đầy đủ thuật toán tìm chu trình, tôi khuyên bạn nên đọc đề xuất gốc từ Neil Schemenauer và tính năng từ mã nguồn của CPython. Ngoài ra, các câu trả lời của Quora và bài đăng trên blog The Garbage Collector có thể hữu ích Lưu ý rằng, sự cố với trình hoàn thiện, được mô tả trong đề xuất ban đầu, đã được khắc phục kể từ Python 3. 4. Bạn có thể đọc về nó trong PEP 442 Mẹo hiệu suấtChu kỳ có thể dễ dàng xảy ra trong cuộc sống thực. Thông thường, bạn gặp chúng trong biểu đồ, danh sách liên kết hoặc trong cấu trúc, trong đó bạn cần theo dõi mối quan hệ giữa các đối tượng. Nếu chương trình của bạn có khối lượng công việc lớn và yêu cầu độ trễ thấp, bạn cần tránh các chu kỳ tham chiếu nhất có thể Để tránh tham chiếu vòng trong mã của bạn, bạn có thể sử dụng tham chiếu yếu, được triển khai trong mô-đun 3. Không giống như các tham chiếu thông thường, 4 không tăng số lượng tham chiếu và trả về 5 nếu một đối tượng bị hủyTrong một số trường hợp, sẽ rất hữu ích khi tắt GC và sử dụng thủ công. Bộ sưu tập tự động có thể bị vô hiệu hóa bằng cách gọi 6. Để chạy quy trình thu thập theo cách thủ công, bạn cần sử dụng 7Cách tìm và gỡ lỗi các chu trình tham chiếuGỡ lỗi các chu kỳ tham chiếu có thể rất khó chịu, đặc biệt là khi bạn sử dụng nhiều thư viện của bên thứ ba Mô-đun gc tiêu chuẩn cung cấp rất nhiều trình trợ giúp hữu ích có thể giúp gỡ lỗi. Nếu bạn đặt cờ gỡ lỗi thành 8, tất cả các đối tượng không thể truy cập được tìm thấy sẽ được thêm vào danh sách 9
Khi bạn đã xác định được một điểm có vấn đề trong mã của mình, bạn có thể khám phá trực quan các mối quan hệ của đối tượng bằng cách sử dụng objgraph. Phần kết luậnHầu hết việc thu gom rác được thực hiện bằng thuật toán đếm tham chiếu mà chúng ta không thể điều chỉnh được. Vì vậy, hãy lưu ý các chi tiết triển khai cụ thể, nhưng đừng quá lo lắng về các sự cố tiềm ẩn của GC Hy vọng rằng, bạn đã học được một cái gì đó mới. Nếu bạn có bất kỳ câu hỏi nào còn lại, tôi sẽ vui lòng trả lời chúng trong phần bình luận bên dưới Bài đăng phổ biến trong danh mục Python28 Tháng Chín, 2017Quản lý bộ nhớ trong Python09 Tháng Năm, 2018Trích xuất văn bản từ HTML bằng Python. một cách tiếp cận rất nhanh21 Tháng Giêng, 2018Hiểu nội bộ của các lớp Python03 Tháng Tư, 2018Thủ thuật tối ưu hóa trong Python. danh sách và bộ dữ liệu10 Tháng Tám, 2018Cách Python tiết kiệm bộ nhớ khi lưu trữ chuỗi29 Tháng Mười Hai, 2017Cấu trúc dữ liệu thưa thớt trong Pythonpython , nội bộ cpython, bộ nhớ, python nâng cao Chia sẻ Bình luận
|