Làm thế nào để thu gom rác diễn ra trong python?

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

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ác

Trong 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

a = [1, 2, 3]
b = a

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 Đối tượng, Loại và Số tham chiếu để được giải thích chi tiết

Ví dụ, trong đó số lượng tham chiếu tăng

  • toán tử gán
  • truyền đối số
  • nối thêm một đối tượng vào danh sách [số lượng tham chiếu của đối tượng sẽ được tăng lên]

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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
7

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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
8

Đây là một ví dụ đơn giản

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]

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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
9 để loại bỏ một biến và tham chiếu của nó [không phải chính đối tượng đó]. Điều này thường hữu ích khi làm việc trong sổ ghi chép Jupyter vì tất cả các biến ô đều sử dụng phạm vi toàn cầu

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,

import gc

# We use ctypes moule  to access our unreachable objects by memory address.
class PyObject[ctypes.Structure]:
    _fields_ = [["refcnt", ctypes.c_long]]


gc.disable[]  # Disable generational gc

lst = []
lst.append[lst]

# Store address of the list
lst_address = id[lst]

# Destroy the lst reference
del lst

object_1 = {}
object_2 = {}
object_1['obj2'] = object_2
object_2['obj1'] = object_1

obj_address = id[object_1]

# Destroy references
del object_1, object_2

# Uncomment if you want to manually run garbage collection process 
# gc.collect[]

# Check the reference count
print[PyObject.from_address[obj_address].refcnt]
print[PyObject.from_address[lst_address].refcnt]
0 và
import gc

# We use ctypes moule  to access our unreachable objects by memory address.
class PyObject[ctypes.Structure]:
    _fields_ = [["refcnt", ctypes.c_long]]


gc.disable[]  # Disable generational gc

lst = []
lst.append[lst]

# Store address of the list
lst_address = id[lst]

# Destroy the lst reference
del lst

object_1 = {}
object_2 = {}
object_1['obj2'] = object_2
object_2['obj1'] = object_1

obj_address = id[object_1]

# Destroy references
del object_1, object_2

# Uncomment if you want to manually run garbage collection process 
# gc.collect[]

# Check the reference count
print[PyObject.from_address[obj_address].refcnt]
print[PyObject.from_address[lst_address].refcnt]
1 đang trỏ đến nhau. Số lượng tham chiếu cho các đối tượng như vậy luôn ít nhất là 1

Để hiểu rõ hơn, bạn có thể chơi với một ví dụ Python đơn giản

import gc

# We use ctypes moule  to access our unreachable objects by memory address.
class PyObject[ctypes.Structure]:
    _fields_ = [["refcnt", ctypes.c_long]]


gc.disable[]  # Disable generational gc

lst = []
lst.append[lst]

# Store address of the list
lst_address = id[lst]

# Destroy the lst reference
del lst

object_1 = {}
object_2 = {}
object_1['obj2'] = object_2
object_2['obj1'] = object_1

obj_address = id[object_1]

# Destroy references
del object_1, object_2

# Uncomment if you want to manually run garbage collection process 
# gc.collect[]

# Check the reference count
print[PyObject.from_address[obj_address].refcnt]
print[PyObject.from_address[lst_address].refcnt]

Trong ví dụ trên, câu lệnh

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
9 loại bỏ các tham chiếu đến các đối tượng của chúng ta [i. e. , giảm số tham chiếu đi 1]. Sau khi Python thực thi câu lệnh
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
9, các đối tượng của chúng ta không thể truy cập được từ mã Python nữa. Tuy nhiên, những đối tượng như vậy vẫn nằm trong bộ nhớ. Điều đó xảy ra bởi vì chúng vẫn đang tham chiếu lẫn nhau và số lượng tham chiếu của mỗi đối tượng là 1. Bạn có thể khám phá một cách trực quan các mối quan hệ như vậy bằng cách sử dụng mô-đun objgraph

Để 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 có các yêu cầu bổ sung để đượ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 hàm

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
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
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
2

Cách tìm chu kỳ tham chiếu

Thậ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 đủ về 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à thu thập chức 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ất

Chu 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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
3. Không giống như các tham chiếu thông thường,
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
4 không tăng số lượng tham chiếu và trả về
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
5 nếu một đối tượng bị hủy

Trong 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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
6. Để chạy thủ công quy trình thu thập, bạn cần sử dụng
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
7

Cách tìm và gỡ lỗi các chu trình tham chiếu

Gỡ 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

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
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
import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
9

import sys

foo = []

# 2 references, 1 from the foo var and 1 from getrefcount
print[sys.getrefcount[foo]]


def bar[a]:
    # 4 references
    # from the foo var, function argument, getrefcount and Python's function stack
    print[sys.getrefcount[a]]


bar[foo]
# 2 references, the function scope is destroyed
print[sys.getrefcount[foo]]
2

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

Sự kết luận

Hầ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 Python

28 Tháng Chín, 2017

Quản lý bộ nhớ trong Python

09 Tháng Năm, 2018

Trích xuất văn bản từ HTML bằng Python. một cách tiếp cận rất nhanh

21 Tháng Giêng, 2018

Hiểu nội bộ của các lớp Python

03 Tháng Tư, 2018

Thủ thuật tối ưu hóa trong Python. danh sách và bộ dữ liệu

10 Tháng Tám, 2018

Cách Python tiết kiệm bộ nhớ khi lưu trữ chuỗi

29 Tháng Mười Hai, 2017

Cấu trúc dữ liệu thưa thớt trong Python

python ,  nội bộ cpython,  bộ nhớ,  python nâng cao

Đăng lại

  • liên kết
  • điện báo
  • VK
  • reddit
  • tin tặc
  • Twitter

  • RSS

    Bình luận

    • Bob Hyman 5 năm, 1 tháng trước [từ disqus] #

      Mô tả rất thú vị và hữu ích về tình trạng hiện tại ở Cython

      Mọi thứ có khác ở những con trăn khác không? . g, IP Python

      Có dự án nào đang được tiến hành để cải thiện bộ nhớ MGMT trong python không?

      Đáp lại

      • Artem 5 năm, 1 tháng trước [từ disqus] #

        Mỗi lần triển khai Python sử dụng trình thu thập riêng của nó. Ví dụ: Jyton sử dụng gc tiêu chuẩn của Java [vì nó chạy trên JVM] và PyPy sử dụng thuật toán Đánh dấu và Quét. Gc của PyPy phức tạp hơn của CPython và có thêm các tối ưu hóa http. // tài liệu. pypy. org/vi/phát hành-2. 4. x/garbage_collection. html

        Tôi không biết về bất kỳ thay đổi nào trong IPython vì nó chỉ là một trình bao tương tác chạy trên CPython

        Về quản lý bộ nhớ, có hàng chục đề xuất trong chỉ mục PEP, nhưng chỉ một số trong số chúng sẽ được chấp nhận trong tương lai

        Đáp lại

    • Madison 5 năm, 1 tháng trước [từ disqus] #

      bài viết hay. Một điều chỉnh nhỏ đáng thực hiện là không phải tất cả các câu lệnh khối đều đưa ra một phạm vi thực thi mới. Đặc biệt, một câu lệnh

      import gc
      
      # We use ctypes moule  to access our unreachable objects by memory address.
      class PyObject[ctypes.Structure]:
          _fields_ = [["refcnt", ctypes.c_long]]
      
      
      gc.disable[]  # Disable generational gc
      
      lst = []
      lst.append[lst]
      
      # Store address of the list
      lst_address = id[lst]
      
      # Destroy the lst reference
      del lst
      
      object_1 = {}
      object_2 = {}
      object_1['obj2'] = object_2
      object_2['obj1'] = object_1
      
      obj_address = id[object_1]
      
      # Destroy references
      del object_1, object_2
      
      # Uncomment if you want to manually run garbage collection process 
      # gc.collect[]
      
      # Check the reference count
      print[PyObject.from_address[obj_address].refcnt]
      print[PyObject.from_address[lst_address].refcnt]
      
      0 không có phạm vi cục bộ của riêng nó hơn một câu lệnh
      import gc
      
      # We use ctypes moule  to access our unreachable objects by memory address.
      class PyObject[ctypes.Structure]:
          _fields_ = [["refcnt", ctypes.c_long]]
      
      
      gc.disable[]  # Disable generational gc
      
      lst = []
      lst.append[lst]
      
      # Store address of the list
      lst_address = id[lst]
      
      # Destroy the lst reference
      del lst
      
      object_1 = {}
      object_2 = {}
      object_1['obj2'] = object_2
      object_2['obj1'] = object_1
      
      obj_address = id[object_1]
      
      # Destroy references
      del object_1, object_2
      
      # Uncomment if you want to manually run garbage collection process 
      # gc.collect[]
      
      # Check the reference count
      print[PyObject.from_address[obj_address].refcnt]
      print[PyObject.from_address[lst_address].refcnt]
      
      1. Đối với phần lớn điều này, điều này chỉ áp dụng cho câu lệnh
      import gc
      
      # We use ctypes moule  to access our unreachable objects by memory address.
      class PyObject[ctypes.Structure]:
          _fields_ = [["refcnt", ctypes.c_long]]
      
      
      gc.disable[]  # Disable generational gc
      
      lst = []
      lst.append[lst]
      
      # Store address of the list
      lst_address = id[lst]
      
      # Destroy the lst reference
      del lst
      
      object_1 = {}
      object_2 = {}
      object_1['obj2'] = object_2
      object_2['obj1'] = object_1
      
      obj_address = id[object_1]
      
      # Destroy references
      del object_1, object_2
      
      # Uncomment if you want to manually run garbage collection process 
      # gc.collect[]
      
      # Check the reference count
      print[PyObject.from_address[obj_address].refcnt]
      print[PyObject.from_address[lst_address].refcnt]
      
      2 và
      import gc
      
      # We use ctypes moule  to access our unreachable objects by memory address.
      class PyObject[ctypes.Structure]:
          _fields_ = [["refcnt", ctypes.c_long]]
      
      
      gc.disable[]  # Disable generational gc
      
      lst = []
      lst.append[lst]
      
      # Store address of the list
      lst_address = id[lst]
      
      # Destroy the lst reference
      del lst
      
      object_1 = {}
      object_2 = {}
      object_1['obj2'] = object_2
      object_2['obj1'] = object_1
      
      obj_address = id[object_1]
      
      # Destroy references
      del object_1, object_2
      
      # Uncomment if you want to manually run garbage collection process 
      # gc.collect[]
      
      # Check the reference count
      print[PyObject.from_address[obj_address].refcnt]
      print[PyObject.from_address[lst_address].refcnt]
      
      3

      Đáp lại

      • Artem 5 năm, 1 tháng trước [từ disqus] #

        Cảm ơn, bạn nói đúng. Tôi đang suy nghĩ về việc vào/ra khỏi bối cảnh

        Đáp lại

    • ben 3 năm, 9 tháng trước [từ disqus] #

      Cảm ơn vì lời giải thích. Sau đó, bạn có thể vui lòng xác nhận rằng việc nhập gc vào sổ ghi chép jupyter là vô nghĩa không?

      Đáp lại

    • Alice 2 năm, 4 tháng trước #

      Viết tốt

      Đáp lại

    • Simon 2 năm, 3 tháng trước #

      Tôi không hiểu tại sao khi bạn chuyển một biến cho một hàm, nó có thêm hai số tham chiếu thay vì một. Bạn đã nói rằng nó có một từ đối số hàm và một từ ngăn xếp hàm của Python. Tôi không biết ngăn xếp chức năng này là gì. Nếu không thì đây là một bài báo tuyệt vời

      Đáp lại

      • Artem 2 năm, 3 tháng trước #

        Ngăn xếp hàm theo dõi tất cả các biến cục bộ có sẵn bên trong hàm

        Đáp lại

        • Tom 2 tháng, 1 tuần trước #

          Tôi xin lỗi, nó có thể là một sai lầm

          Đáp lại

    • kanch 2 năm, 3 tháng trước #

      Xin chào, bài viết của bạn giúp tôi rất nhiều trong việc giảm mức sử dụng bộ nhớ ứng dụng python của tôi

      Tôi có thể dịch nó sang tiếng Trung và đăng lại với tham chiếu đến blog của tôi không?

      Đáp lại

      • Artem 2 năm, 3 tháng trước #

        Chắc chắn, bạn có thể dịch nó. Chỉ cần liên kết bài viết của tôi trong bản dịch của bạn

        Đáp lại

    • jbo 2 năm, 1 tháng trước #

      Giải thích rất tốt, chỉ thích đọc nó và các bài báo khác của bạn. Hãy tiếp tục phát huy

      Đáp lại

    • ferdizera 1 năm, 12 tháng trước #

      Đơn giản và khách quan. bài viết hay. lời giải thích tốt đẹp

      Đáp lại

    • jb 1 năm 9 tháng trước #

      Cảm ơn bạn, rõ ràng và hữu ích

      Đáp lại

    • Lokumcu Hayri 1 năm, 9 tháng trước #

      Không nói nhảm, chỉ giải thích và ví dụ chính xác. Cảm ơn

      Đáp lại

    • maz 1 năm, 7 tháng trước #

      Tôi nghĩ ý của bạn trong câu này là "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 lệnh gc. hàm get_threshold. "gc. set_threshold. btw Cảm ơn vì blog của bạn, thực sự hữu ích

      Đáp lại

    • hans 1 năm, 6 tháng trước #

      "Đ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"

      Bạn có nghĩa là trong khi thay vì "cho đến khi" ở đây?

      Việc thu gom rác diễn ra như thế nào?

      Miễn là một đối tượng đang được tham chiếu, JVM coi nó còn sống. Khi một đối tượng không còn được tham chiếu và do đó mã ứng dụng không thể truy cập được, bộ thu gom rác sẽ loại bỏ nó và lấy lại bộ nhớ không sử dụng

      Tần suất thu gom rác Python như thế nào?

      Bất cứ khi nào số lượng tham chiếu giảm xuống 0, đối tượng sẽ bị xóa ngay lập tức. 295 * được xử lý ngay tại thời điểm đó. Bộ sưu tập đầy đủ được kích hoạt khi số lượng đối tượng mới lớn hơn 25% số lượng đối tượng hiện có .

    Chủ Đề