Bạn có thể bị rò rỉ bộ nhớ trong python không?

Trong bài viết này, chúng tôi đề cập đến rò rỉ bộ nhớ là gì, nguyên nhân gây rò rỉ bộ nhớ và cách xử lý rò rỉ bộ nhớ trong python, ngoài ra, chúng tôi thấy những lợi ích của việc sử dụng python đối với rò rỉ bộ nhớ

Bộ nhớ bị rò rỉ

Rò rỉ bộ nhớ là một vấn đề, khi bộ nhớ tạo cho bất kỳ biến, tham chiếu, đối tượng nào và quên xóa nó, sau đó chúng tạo ra sự cố cho các chương trình như daemon và máy chủ không bao giờ kết thúc

Khi một chương trình đang chạy, nó sẽ thu thập bộ nhớ từ RAM không phụ thuộc vào ngôn ngữ nhưng phụ thuộc vào kiến ​​trúc máy tính và hệ điều hành đang được sử dụng trong hệ thống

Bạn có thể bị rò rỉ bộ nhớ trong python không?
1. 1 Các loại bộ nhớ Chương trình

Bộ nhớ chương trình chia làm 4 loại như hình 1. 1

• Đầu tiên là Hướng dẫn để giữ các hướng dẫn được cung cấp qua mã của chúng tôi.
• Tiếp theo là Dữ liệu lưu trữ biến có thể là cục bộ hoặc toàn cục.
• Điều thứ ba quan trọng tôi. e. , Stack được sử dụng trong thời gian chạy e. g. , thực thi các phương thức/hàm, vòng lặp, đệ quy, v.v.
• Cái cuối cùng là bộ nhớ heap cấp phát bộ nhớ cho các cấp phát động như malloc, calloc hoặc cấp phát lại các giá trị.

Các khối Hướng dẫn và Dữ liệu tiêu thụ một lượng bộ nhớ cố định khi bắt đầu thực hiện chương trình. Nhưng các khối của Stack và Heap khác nhau về mức tiêu thụ bộ nhớ

Trong vòng đời của chương trình, sẽ có các thao tác ghi và xóa thường xuyên trong bộ nhớ, chẳng hạn như gọi hàm, thực hiện các vòng lặp, mở tệp, chuyển hướng trang, v.v.

Trong các ngôn ngữ nguyên thủy như C và java có 2 trạng thái là Consumed và Free, giả sử chúng ta tạo 1 biến thì bộ nhớ sẽ được cấp phát. trong khi cấp phát bộ nhớ, trình thông dịch cho biết biến đang ở trạng thái tiêu thụ, sau khi chương trình thực thi thành công, giải phóng bộ nhớ cho biến đó, bằng cách gán trạng thái trống cho biến đó. Tại thời điểm này không lãng phí bộ nhớ, nhưng do một số vấn đề hoặc lý do nào đó, bộ nhớ cho biến đó không còn trống nên nó gây ra vấn đề rò rỉ bộ nhớ

Để khắc phục và khắc phục chúng, chúng tôi cần đo bộ nhớ được sử dụng bởi từng đoạn mã tôi. e. , cấu hình bộ nhớ

Rò rỉ bộ nhớ trong Python

Trong Python mọi thứ đều là đối tượng, python thường sử dụng 2 khối bộ nhớ phụ là Bộ nhớ Heap và Bộ nhớ ngăn xếp để lưu trữ hàm, dữ liệu, biến và đối tượng, v.v.

Bộ nhớ ngăn xếp được sử dụng để lưu trữ các phương thức, biến và bộ nhớ Heap được sử dụng để lưu trữ các đối tượng thực tế (e. g. , giá trị nguyên), theo mặc định, chương trình thực thi từ phương thức chính

def f2(x):
    x = x + 1
    return x


def f1(x):
    x = x*2
    y = f2(x)
    return y


if __name__ == '__main__':
    y = 5
    z = f1(y)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Liên quan đến ví dụ, chúng tôi hiển thị dưới dạng sơ đồ

Bạn có thể bị rò rỉ bộ nhớ trong python không?

Ở đây, theo quy tắc, phương thức chính bắt đầu thực thi trước và cấp phát bộ nhớ cho phương thức đó trong không gian ngăn xếp cùng với các biến có trong phương thức chính, i. e. , y = 5, vì vậy 5 là đối tượng được lưu trữ trong bộ nhớ heap và tham chiếu được lưu trữ ở vị trí y trong không gian ngăn xếp

Sau đó, nó gọi hàm f1() để một khối bộ nhớ khác sẽ được tạo trong ngăn xếp và biến x được tạo với một đối tượng mới đi vào không gian heap giống như các hàm khác, 3 phương thức được gọi và bộ nhớ được phân bổ cho từng phương thức cùng với các tham chiếu

Khi hoàn thành giá trị trả về của hàm f2() được chuyển cho y và xóa các tham chiếu của tất cả các biến và xóa khối bộ nhớ khỏi không gian ngăn xếp

Bạn có thể bị rò rỉ bộ nhớ trong python không?

Điều tương tự cũng xảy ra khi f1() trả về, lưu ý rằng không có biến nào tham chiếu đến 10, vì vậy điều này được gọi là rò rỉ bộ nhớ

Bạn có thể bị rò rỉ bộ nhớ trong python không?

sẽ thấy điều gì đã xảy ra trong python nếu không có điểm biến nào cho bất kỳ đối tượng nào, làm thế nào chúng ta có thể xóa nó

Các phương pháp loại bỏ rò rỉ bộ nhớ

Chúng ta hãy lấy ví dụ tương tự khi chương trình thực thi, trình thông dịch duy trì bảng nơi nó theo dõi đối tượng và số lượng tham chiếu

Đối tượngSố tài liệu tham khảo51101111

Bàn. 1. 0 khi chương trình thực hiện tất cả các chức năng

Đối tượngSố tài liệu tham khảo51101111

Bàn. 1. 1 khi f2() kết thúc

Đối tượngSố tham chiếu51100 (Đối tượng đã chết)111

Bàn. 1. 2 khi tất cả (main, f1(), f2()) chức năng kết thúc

Theo bảng 1. 0 và 1. 1 thì cả 3 đối tượng đều có tham chiếu nhưng sau khi f1() thực thi xong thì đối tượng 10 còn 0 tham chiếu tức là chương trình không sử dụng đối tượng 10 nữa và nó còn được gọi là đối tượng Dead

Python có một cơ chế bên trong gọi là Garbage Collector (GC), nó chạy ngay khi số tham chiếu trở thành 0, nó loại bỏ đối tượng chết khỏi bộ nhớ và giải phóng khối đó. Thuật toán dùng cho Garbage Collection được gọi là Reference Counting

Đoạn mã

import weakref


def f2(x):
    x = x + 1
    return x


def f1(x):
    x = x*2
    y = f2(x)
    return y


if __name__ == '__main__':
    y = 5
    z = f1(y)
    print("Memory location", id(f1))
    r = weakref.ref(f1)
    print(r)
    f1 = None
    print(r)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Memory location 2072240612264
<weakref at 0x000001E27B25B138; to 'function' at 0x000001E27B2A63A8 (f1)>
<weakref at 0x000001E27B25B138; dead>

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Ở đây, tôi sửa đổi mã để nhận hoặc truy xuất các tham chiếu của hàm f2(), Vì vậy, đã xóa tham chiếu của f2() bằng cách gán nó cho Không, sau đó, kết quả là f2() nằm trong một đối tượng chết, vì vậy trình thu gom rác sẽ xóa

Nhưng nếu chúng ta nói về các thuật ngữ thực tế thì nó không dễ như chúng ta tưởng. Đôi khi, trình thu gom rác không kiểm tra được các đối tượng không được ước tính, dẫn đến rò rỉ bộ nhớ trong Python. Cuối cùng, các chương trình python hết bộ nhớ vì nó bị rò rỉ bộ nhớ. Nó trở thành một thách thức để tìm rò rỉ bộ nhớ trong python và sau đó chữa chúng

Do đó, chúng ta có thể nói rằng rò rỉ bộ nhớ xảy ra trong python khi dữ liệu không sử dụng được chất đống và lập trình viên quên xóa nó. Để chẩn đoán rò rỉ bộ nhớ như vậy từ python, chúng tôi phải thực hiện một quy trình lập hồ sơ bộ nhớ, theo đó chúng tôi có thể đo bộ nhớ được sử dụng bởi từng phần của mã

Đừng hoang mang với từ Lập hồ sơ bộ nhớ vì việc lập hồ sơ bộ nhớ cơ bản khá dễ dàng

Nguyên nhân rò rỉ bộ nhớ trong Python

  1. Để nán lại tất cả các vật thể lớn chưa được giải phóng
  2. Chu kỳ tham chiếu trong mã cũng có thể gây rò rỉ bộ nhớ
  3. Đôi khi các thư viện cơ bản cũng có thể gây rò rỉ bộ nhớ

gỡ lỗi

Trước tiên, bạn có thể gỡ lỗi việc sử dụng bộ nhớ thông qua mô-đun tích hợp bộ thu gom rác (GC). Nó sẽ liệt kê ra tất cả các đối tượng được Garbage Collector biết đến. Nó sẽ giúp bạn tìm ra nơi toàn bộ bộ nhớ đang được sử dụng. Và sau đó bạn có thể lọc nó theo mục đích sử dụng của chúng. Nếu các đối tượng không được sử dụng ngay cả khi nó được tham chiếu. Sau đó, bạn có thể xóa chúng để tránh rò rỉ bộ nhớ trong Python

Nó sẽ in ra tất cả các đối tượng và dữ liệu được tạo ra trong quá trình thực hiện. Nhưng GC trong mô-đun đã xây dựng có một hạn chế là không nêu rõ cách các đối tượng được phân bổ. Vì vậy, cuối cùng nó sẽ không giúp bạn tìm ra để xác định mã chịu trách nhiệm phân bổ các đối tượng gây rò rỉ bộ nhớ

Tracemalloc

Tính năng tốt nhất của Python là mô-đun tích hợp Tracemalloc mới. Vì nó được coi là phù hợp nhất với vấn đề rò rỉ bộ nhớ trong Python. Nó sẽ giúp bạn kết nối một đối tượng với vị trí ban đầu nó được phân bổ

Nó có một dấu vết ngăn xếp sẽ giúp bạn tìm ra cách sử dụng cụ thể của một chức năng phổ biến đang tiêu tốn bộ nhớ trong chương trình. Tracemalloc cho phép bạn theo dõi việc sử dụng bộ nhớ của một đối tượng. Cuối cùng, bạn có thể tìm ra nguyên nhân rò rỉ bộ nhớ trong Python. Vì vậy, nếu bạn biết đối tượng nào đang gây rò rỉ bộ nhớ, bạn hãy sửa hoặc xóa chúng

Nó sẽ giảm hiệu quả dấu chân của bộ nhớ trong chương trình. Đó là lý do tại sao Tracemalloc được biết đến như một phương pháp theo dõi bộ nhớ mạnh mẽ để giảm rò rỉ bộ nhớ trong Python

Để theo dõi hầu hết các khối bộ nhớ do Python cấp phát, mô-đun phải được bắt đầu càng sớm càng tốt bằng cách đặt biến môi trường PYTHONTRACEMALLOC thành 1 hoặc bằng cách sử dụng tùy chọn dòng lệnh -X tracemalloc. dấu vết. hàm start() có thể được gọi trong thời gian chạy để bắt đầu theo dõi phân bổ bộ nhớ Python

ví dụ

1) Hiển thị 10 tệp phân bổ nhiều bộ nhớ nhất

import tracemalloc

tracemalloc.start()

# .. run your application ...

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

print("[ Top 10 ]")
for stat in top_stats[:10]:
    print(stat)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

[ Top 10 ]
<frozen importlib._bootstrap>:716: size=4855 KiB, count=39328, average=126 B
<frozen importlib._bootstrap>:284: size=521 KiB, count=3199, average=167 B
/usr/lib/python3.4/collections/__init__.py:368: size=244 KiB, count=2315, average=108 B
/usr/lib/python3.4/unittest/case.py:381: size=185 KiB, count=779, average=243 B
/usr/lib/python3.4/unittest/case.py:402: size=154 KiB, count=378, average=416 B
/usr/lib/python3.4/abc.py:133: size=88.7 KiB, count=347, average=262 B
<frozen importlib._bootstrap>:1446: size=70.4 KiB, count=911, average=79 B
<frozen importlib._bootstrap>:1454: size=52.0 KiB, count=25, average=2131 B
<string>:5: size=49.7 KiB, count=148, average=344 B
/usr/lib/python3.4/sysconfig.py:411: size=48.0 KiB, count=1, average=48.0 KiB

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

2) Mã để hiển thị truy nguyên của khối bộ nhớ lớn nhất

import tracemalloc

# Store 25 frames
tracemalloc.start(25)

# .. run your application ...

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('traceback')

# pick the biggest memory block
stat = top_stats[0]
print("%s memory blocks: %.1f KiB" % (stat.count, stat.size / 1024))
for line in stat.traceback.format():
    print(line)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

903 memory blocks: 870.1 KiB
  File "", line 716
  File "", line 1036
  File "", line 934
  File "", line 1068
  File "", line 619
  File "", line 1581
  File "", line 1614
  File "/usr/lib/python3.4/doctest.py", line 101
    import pdb
  File "", line 284
  File "", line 938
  File "", line 1068
  File "", line 619
  File "", line 1581
  File "", line 1614
  File "/usr/lib/python3.4/test/support/__init__.py", line 1728
    import doctest
  File "/usr/lib/python3.4/test/test_pickletools.py", line 21
    support.run_doctest(pickletools)
  File "/usr/lib/python3.4/test/regrtest.py", line 1276
    test_runner()
  File "/usr/lib/python3.4/test/regrtest.py", line 976
    display_failure=not verbose)
  File "/usr/lib/python3.4/test/regrtest.py", line 761
    match_tests=ns.match_tests)
  File "/usr/lib/python3.4/test/regrtest.py", line 1563
    main()
  File "/usr/lib/python3.4/test/__main__.py", line 3
    regrtest.main_in_temp_cwd()
  File "/usr/lib/python3.4/runpy.py", line 73
    exec(code, run_globals)
  File "/usr/lib/python3.4/runpy.py", line 160
    "__main__", fname, loader, pkg_name)

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Ví dụ về đầu ra của bộ thử nghiệm Python (truy ngược giới hạn ở 25 khung hình)

Chúng ta có thể thấy rằng phần lớn bộ nhớ được phân bổ trong mô-đun importlib để tải dữ liệu (mã byte và hằng số) từ các mô-đun. 870. 1 KiB. Traceback là nơi importlib tải dữ liệu gần đây nhất. trên dòng pdb nhập của mô-đun doctest. Truy nguyên có thể thay đổi nếu một mô-đun mới được tải

Ưu & Nhược điểm

  • ưu
    • Sử dụng bộ nhớ tối ưu
    • Rất nhanh và nhanh
  • Nhược điểm
    • Làm chậm tốc độ thực thi do thường xuyên gọi GC

Sự kết luận

Python là một trong những ngôn ngữ lập trình hướng đối tượng tốt nhất trên thế giới. Nó được nhiều công ty lớn sử dụng cho nhiều dự án của họ như Google, YouTube, v.v. Nó được biết đến với hiệu quả của nó. Nhưng nó cũng bị rò rỉ bộ nhớ như các chương trình khác. CPython trong python giúp phân bổ và giải phóng bộ nhớ trong Python

Nhưng đôi khi một số đối tượng không được giải quyết ngay cả khi chúng không được tham chiếu trong một thời gian dài. Đây là nơi xảy ra rò rỉ bộ nhớ trong Python. Do đó, nó đã trở thành một thách thức đối với tất cả các lập trình viên và nhà phát triển để giải quyết. Cuối cùng, họ đã tìm ra một số cách nhất định để giải quyết vấn đề này như đã đề cập ở trên

Người giới thiệu

https. // tài liệu. con trăn. org/3/library/tracemalloc. html
https. //benbernardblog. com/tracking-down-a-freaky-python-memory-leak/
https. // xếp chồng lên nhau. com/top-5-python-memory-profilers/
https. // tài liệu. con trăn. org/3/sử dụng/dòng lệnh. html#envvar-PYTHONTRACEMALLOC
https. //statanalytica. com/blog/memory-leaks-in-python/

từ chối trách nhiệm. Đây là [blog, bài đăng, tuyên bố, ý kiến] cá nhân. Các quan điểm và ý kiến ​​thể hiện ở đây chỉ là của tác giả và không đại diện cho quan điểm của bất kỳ tổ chức hoặc cá nhân nào mà tác giả có thể liên kết, chuyên nghiệp hoặc cá nhân

Có thể rò rỉ bộ nhớ trong Python không?

Bạn có thể phát hiện rò rỉ bộ nhớ trong Python bằng cách theo dõi hiệu suất của ứng dụng Python thông qua công cụ Giám sát hiệu suất ứng dụng như Scout APM . Khi bạn phát hiện rò rỉ bộ nhớ, có nhiều cách để giải quyết.

Python có quản lý bộ nhớ tốt không?

Hiểu được quản lý bộ nhớ là một siêu năng lực sẽ giúp bạn thiết kế các ứng dụng sử dụng bộ nhớ hiệu quả và giúp gỡ lỗi các vấn đề về bộ nhớ dễ dàng hơn . Tham gia cùng Rupesh Mishra để tìm hiểu sâu về nội dung của CPython.