Python - Memory Management

Trong Python, memory management là tự động, nó liên quan đến việc quản lý một vùng nhớ riêng tư chứa tất cả các đối tượng Python và data structures . Trình quản lý bộ nhớ Python nội bộ đảm bảo việc cấp phát và giải phóng bộ nhớ này một cách hiệu quả. Hướng dẫn này sẽ khám phá các cơ chế quản lý bộ nhớ của Python, bao gồm thu gom rác, đếm tham chiếu, và cách các biến được lưu trữ trên ngăn xếp và vùng nhớ.

Memory Management Components

Các thành phần quản lý bộ nhớ của Python cung cấp việc sử dụng tài nguyên bộ nhớ hiệu quả và hợp lý trong suốt quá trình thực thi các chương trình Python. Python có ba thành phần quản lý bộ nhớ −

  • Private Heap : Acts as the main storage for all Python objects and data. It is managed internally by the Python memory manager.
  • Raw Memory Allocator : This low-level component directly interacts with the operating system to reserve memory space in Python's private heap. It ensures there's enough room for Python's data structures and objects.
  • Object-Specific Allocators : On top of the raw memory allocator, several object-specific allocators manage memory for different types of objects, such as integers, strings, tuples, and dictionaries.

Memory Allocation in Python

Python quản lý việc cấp phát bộ nhớ theo hai cách chính - Stack và Heap.

Stack − Static Memory Allocation

Trong phân bổ bộ nhớ tĩnh, bộ nhớ được phân bổ tại thời điểm biên dịch và được lưu trữ trong ngăn xếp. Điều này điển hình cho các ngăn xếp gọi hàm và tham chiếu biến. Ngăn xếp là một vùng bộ nhớ được sử dụng để lưu trữ các biến cục bộ và thông tin gọi hàm. Nó hoạt động theo nguyên tắc Last-In-First-Out (LIFO), trong đó mục được thêm vào gần đây nhất sẽ là mục đầu tiên bị loại bỏ.

Ngăn xếp thường được sử dụng cho các biến của các kiểu dữ liệu nguyên thủy, chẳng hạn như số, boolean và ký tự. Những biến này có kích thước bộ nhớ cố định, được biết đến tại thời điểm biên dịch.

Example

Hãy xem một ví dụ để minh họa cách mà các biến kiểu nguyên thủy được lưu trữ trên ngăn xếp. Trong ví dụ trên, các biến có tên x, y và z là các biến cục bộ trong hàm có tên example_function(). Chúng được lưu trữ trên ngăn xếp, và khi quá trình thực thi hàm hoàn tất, chúng sẽ tự động được loại bỏ khỏi ngăn xếp.

def my_function():
   x = 5
   y = True
   z = 'Hello'
   return x, y, z

print(my_function())
print(x, y, z)

Khi thực thi chương trình trên, bạn sẽ nhận được output

(5, True, 'Hello')
Traceback (most recent call last):
  File "/home/cg/root/71937/main.py", line 8, in <module>
    print(x, y, z)
NameError: name 'x' is not defined

Heap − Dynamic Memory Allocation

Cấp phát bộ nhớ động xảy ra trong thời gian chạy cho các đối tượng và cấu trúc dữ liệu của các kiểu không nguyên thủy. Dữ liệu thực tế của các đối tượng này được lưu trữ trong heap, trong khi các tham chiếu đến chúng được lưu trữ trên stack.

Example

Hãy cùng quan sát một ví dụ về việc tạo một danh sách động, cấp phát bộ nhớ trong heap.

a = [0]*10
print(a)

Output

Khi thực thi chương trình trên, bạn sẽ nhận được các kết quả sau −

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Garbage Collection in Python

Quá trình thu gom rác trong Python là quá trình tự động giải phóng bộ nhớ không còn được sử dụng bởi các đối tượng, giúp làm cho bộ nhớ đó có sẵn cho các đối tượng khác. Bộ thu gom rác của Python chạy trong suốt quá trình thực thi chương trình và kích hoạt khi reference count của một đối tượng giảm xuống bằng không.

Reference Counting

Cơ chế thu gom rác chính của Python là đếm tham chiếu. Mỗi đối tượng trong Python duy trì một đếm tham chiếu theo dõi số lượng bí danh (hoặc tham chiếu) trỏ đến nó. Khi đếm tham chiếu của một đối tượng giảm xuống bằng không, bộ thu gom rác sẽ giải phóng đối tượng đó.

Cách hoạt động của việc đếm tham chiếu như sau −

  • Increasing Reference Count − It happens when a new reference to an object is created, the reference count increases.
  • Decreasing Reference Count − When a reference to an object is removed or goes out of scope, the reference count decreases.

Example

Dưới đây là một ví dụ minh họa cách thức hoạt động của việc đếm tham chiếu trong Python.

import sys

# Create a string object
name = "Tutorialspoint"
print("Initial reference count:", sys.getrefcount(name))  

# Assign the same string to another variable
other_name = "Tutorialspoint"
print("Reference count after assignment:", sys.getrefcount(name)) 

# Concatenate the string with another string
string_sum = name + ' Python'
print("Reference count after concatenation:", sys.getrefcount(name)) 

# Put the name inside a list multiple times
list_of_names = [name, name, name]
print("Reference count after creating a list with 'name' 3 times:", sys.getrefcount(name)) 

# Deleting one more reference to 'name'
del other_name
print("Reference count after deleting 'other_name':", sys.getrefcount(name))  

# Deleting the list reference
del list_of_names
print("Reference count after deleting the list:", sys.getrefcount(name))  

Output

Khi thực thi chương trình trên, bạn sẽ nhận được các kết quả sau −

Initial reference count: 4
Reference count after assignment: 5
Reference count after concatenation: 5
Reference count after creating a list with 'name' 3 times: 8
Reference count after deleting 'other_name': 7
Reference count after deleting the list: 4