Bộ nhớ Python

Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách Python quản lý bộ nhớ hoặc cách Python xử lý nội bộ ngày của chúng ta. Chúng ta sẽ đi sâu vào chủ đề này để hiểu hoạt động bên trong của Python và cách nó xử lý bộ nhớ

Hướng dẫn này sẽ giúp hiểu sâu về quản lý bộ nhớ Python. Khi chúng tôi thực thi tập lệnh Python của mình, có rất nhiều logic chạy phía sau trong bộ nhớ Python để làm cho mã hiệu quả

Giới thiệu

Quản lý bộ nhớ rất quan trọng đối với các nhà phát triển phần mềm để làm việc hiệu quả với bất kỳ ngôn ngữ lập trình nào. Như chúng ta đã biết, Python là một ngôn ngữ lập trình nổi tiếng và được sử dụng rộng rãi. Nó được sử dụng gần như trong mọi lĩnh vực kỹ thuật. Trái ngược với ngôn ngữ lập trình, quản lý bộ nhớ liên quan đến việc viết mã hiệu quả về bộ nhớ. Chúng ta không thể bỏ qua tầm quan trọng của việc quản lý bộ nhớ trong khi triển khai một lượng lớn dữ liệu. Quản lý bộ nhớ không đúng cách dẫn đến ứng dụng và các thành phần phía máy chủ bị chậm. Nó cũng trở thành lý do làm việc không đúng cách. Nếu bộ nhớ không được xử lý tốt, sẽ mất nhiều thời gian trong quá trình tiền xử lý dữ liệu

Trong Python, bộ nhớ được quản lý bởi trình quản lý Python để xác định vị trí đặt dữ liệu ứng dụng vào bộ nhớ. Vì vậy, chúng ta phải có kiến ​​thức về trình quản lý bộ nhớ Python để viết mã hiệu quả và mã có thể bảo trì

Giả sử bộ nhớ giống như một cuốn sách trống và chúng ta muốn viết bất cứ thứ gì trên trang sách. Sau đó, chúng tôi ghi dữ liệu bất kỳ dữ liệu nào người quản lý tìm thấy không gian trống trong cuốn sách và cung cấp cho ứng dụng. Thủ tục cung cấp bộ nhớ cho các đối tượng được gọi là cấp phát

Mặt khác, khi dữ liệu không còn được sử dụng, nó có thể bị xóa bởi trình quản lý bộ nhớ Python. Nhưng câu hỏi là, làm thế nào?

Phân bổ bộ nhớ Python

Cấp phát bộ nhớ là một phần thiết yếu trong quản lý bộ nhớ cho nhà phát triển. Quá trình này về cơ bản phân bổ không gian trống trong bộ nhớ ảo của máy tính và có hai loại bộ nhớ ảo hoạt động trong khi thực thi chương trình

  • Cấp phát bộ nhớ tĩnh
  • Cấp phát bộ nhớ động

Phân bổ bộ nhớ tĩnh -

Cấp phát bộ nhớ tĩnh xảy ra tại thời điểm biên dịch. Ví dụ - Trong C/C++, chúng ta khai báo một mảng tĩnh với kích thước cố định. Bộ nhớ được cấp phát tại thời điểm biên dịch. Tuy nhiên, chúng ta không thể sử dụng lại bộ nhớ trong chương trình tiếp theo

Phân bổ ngăn xếp

Cấu trúc dữ liệu Stack được sử dụng để lưu trữ bộ nhớ tĩnh. Nó chỉ cần thiết bên trong hàm cụ thể hoặc lệnh gọi phương thức. Hàm được thêm vào ngăn xếp cuộc gọi của chương trình bất cứ khi nào chúng ta gọi nó. Phép gán biến bên trong hàm được lưu trữ tạm thời trong ngăn xếp lệnh gọi hàm; . Trình biên dịch xử lý tất cả các quy trình này, vì vậy chúng tôi không cần phải lo lắng về nó

Ngăn xếp cuộc gọi [cấu trúc dữ liệu ngăn xếp] chứa dữ liệu hoạt động của chương trình như chương trình con hoặc lệnh gọi hàm theo thứ tự chúng được gọi. Các chức năng này được bật lên từ ngăn xếp khi chúng tôi gọi

Cấp phát bộ nhớ động

Không giống như cấp phát bộ nhớ tĩnh, Bộ nhớ động cấp phát bộ nhớ trong thời gian chạy chương trình. Ví dụ - Trong C/C++, có định sẵn kích thước của số nguyên kiểu dữ liệu float nhưng không có định sẵn kích thước của các kiểu dữ liệu. Bộ nhớ được phân bổ cho các đối tượng trong thời gian chạy. Chúng tôi sử dụng Heap để triển khai quản lý bộ nhớ động. Chúng ta có thể sử dụng bộ nhớ trong suốt chương trình

Như chúng ta biết, mọi thứ trong Python là một đối tượng có nghĩa là cấp phát bộ nhớ động truyền cảm hứng cho việc quản lý bộ nhớ Python. Trình quản lý bộ nhớ Python tự động biến mất khi đối tượng không còn được sử dụng

Cấp phát bộ nhớ heap

Cấu trúc dữ liệu heap được sử dụng cho bộ nhớ động không liên quan đến việc đặt tên đối tác. Là loại bộ nhớ sử dụng bên ngoài chương trình ở không gian toàn cục. Một trong những ưu điểm tốt nhất của bộ nhớ heap là nó giải phóng không gian bộ nhớ nếu đối tượng không còn được sử dụng hoặc nút bị xóa

Trong ví dụ dưới đây, chúng tôi xác định cách lưu trữ biến của hàm trong ngăn xếp và một đống

Triển khai Python mặc định

Python là một ngôn ngữ lập trình hướng đối tượng mã nguồn mở được triển khai mặc định trong ngôn ngữ lập trình C. Đó là một thực tế rất thú vị - Một ngôn ngữ phổ biến nhất được viết bằng ngôn ngữ khác?

Về cơ bản, ngôn ngữ Python được viết bằng ngôn ngữ tiếng Anh. Tuy nhiên, nó được định nghĩa trong sách hướng dẫn tham khảo mà bản thân nó không hữu ích. Vì vậy, chúng tôi cần một trình thông dịch mã dựa trên quy tắc trong sách hướng dẫn

Lợi ích của việc triển khai mặc định, nó thực thi mã Python trong máy tính và nó cũng chuyển đổi mã Python của chúng tôi thành hướng dẫn. Vì vậy, chúng ta có thể nói rằng việc triển khai mặc định của Python đáp ứng cả hai yêu cầu

Lưu ý - Máy ảo không phải là máy tính vật lý, nhưng chúng được kích hoạt trong phần mềm

Chương trình mà chúng tôi viết bằng ngôn ngữ Python trước tiên sẽ chuyển đổi thành mã byte hướng dẫn liên quan đến máy tính. Máy ảo diễn giải bytecode này

Bộ thu gom rác Python

Như chúng tôi đã giải thích trước đó, Python loại bỏ những đối tượng không còn được sử dụng hoặc có thể nói rằng nó giải phóng không gian bộ nhớ. Quá trình làm biến mất không gian bộ nhớ của đối tượng không cần thiết này được gọi là Garbage Collector. Trình thu gom rác Python bắt đầu thực thi chương trình và được kích hoạt nếu số lượng tham chiếu giảm xuống 0

Khi chúng tôi gán tên mới hoặc đặt nó trong các vùng chứa như từ điển hoặc bộ dữ liệu, số lượng tham chiếu sẽ tăng giá trị của nó. Nếu chúng ta gán lại tham chiếu cho một đối tượng, số lượng tham chiếu sẽ giảm giá trị của nó nếu. Nó cũng giảm giá trị khi tham chiếu của đối tượng nằm ngoài phạm vi hoặc một đối tượng bị xóa

Như chúng ta đã biết, Python sử dụng cấp phát bộ nhớ động được quản lý bởi cấu trúc dữ liệu Heap. Memory Heap chứa các đối tượng và các cấu trúc dữ liệu khác sẽ được sử dụng trong chương trình. Trình quản lý bộ nhớ Python quản lý việc cấp phát hoặc hủy cấp phát không gian bộ nhớ heap thông qua các hàm API

Các đối tượng Python trong bộ nhớ

Như chúng ta đã biết, mọi thứ trong Python đều là đối tượng. Đối tượng có thể đơn giản [chứa số, chuỗi, v.v. ] hoặc vùng chứa [từ điển, danh sách hoặc lớp do người dùng xác định]. Trong Python, chúng ta không cần khai báo biến hoặc kiểu của chúng trước khi sử dụng chúng trong chương trình

Hãy hiểu ví dụ sau

Ví dụ -

đầu ra

10
Traceback [most recent call last]:
  File "", line 1, in 
    print[x]
NameError : name 'a' is not defined

Như chúng ta có thể thấy trong đầu ra ở trên, chúng ta đã gán giá trị cho đối tượng x và in nó. Khi chúng tôi xóa đối tượng x và cố gắng truy cập vào mã tiếp theo, sẽ có lỗi thông báo rằng biến x không được xác định

Do đó, trình thu gom rác Python hoạt động tự động và các lập trình viên không cần phải lo lắng về điều đó, không giống như C

Đếm tham chiếu trong Python

Đếm tham chiếu cho biết có bao nhiêu lần các đối tượng khác tham chiếu đến một đối tượng. Khi một tham chiếu của đối tượng được chỉ định, số lượng đối tượng được tăng lên một. Khi các tham chiếu của một đối tượng bị xóa hoặc bị xóa, số lượng đối tượng sẽ giảm đi. Trình quản lý bộ nhớ Python thực hiện phân bổ lại khi số lượng tham chiếu trở thành 0. Hãy làm cho nó đơn giản để hiểu

Ví dụ -

Giả sử, có hai hoặc nhiều biến chứa cùng một giá trị, vì vậy máy ảo Python thay vì tạo một đối tượng khác có cùng giá trị trong vùng riêng. Nó thực sự làm cho biến thứ hai trỏ đến giá trị hiện có ban đầu trong vùng riêng

Điều này rất có lợi để bảo vệ bộ nhớ, có thể được sử dụng bởi một biến khác


Khi chúng ta gán giá trị cho x. đối tượng số nguyên 10 được tạo trong bộ nhớ Heap và tham chiếu của nó được gán cho x


Trong đoạn mã trên, chúng ta đã gán y = x, có nghĩa là đối tượng y sẽ tham chiếu đến cùng một đối tượng vì Python đã phân bổ cùng một tham chiếu đối tượng cho biến mới nếu đối tượng đã tồn tại với cùng một giá trị

Bây giờ, hãy xem một ví dụ khác

Ví dụ -

đầu ra

x and y do not refer to the same object

Các biến x và y không tham chiếu đến cùng một đối tượng vì x được tăng thêm một, x tạo đối tượng tham chiếu mới và y vẫn tham chiếu đến 10

Chuyển đổi Garbage Collector

Trình thu gom rác Python đã phân loại các đối tượng bằng cách sử dụng thế hệ của nó. Trình thu gom rác Python có ba thế hệ. Khi chúng ta xác định đối tượng mới trong chương trình, vòng đời của nó được xử lý bởi thế hệ đầu tiên của trình thu gom rác. Nếu đối tượng được sử dụng trong một chương trình khác, nó sẽ được kích thích cho thế hệ tiếp theo. Mỗi thế hệ đều có một ngưỡng

Trình thu gom rác sẽ hoạt động nếu vượt quá ngưỡng của số lượng phân bổ trừ đi số lượng phân bổ lại

Chúng tôi có thể sửa đổi giá trị ngưỡng theo cách thủ công bằng cách sử dụng mô-đun GC. Mô-đun này cung cấp phương thức get_threshold[] để kiểm tra giá trị ngưỡng của một thế hệ thu gom rác khác. Hãy hiểu ví dụ sau

Ví dụ -

đầu ra

Trong đầu ra ở trên, giá trị ngưỡng 700 dành cho thế hệ thứ nhất và các giá trị khác dành cho thế hệ thứ hai và thứ ba

Giá trị ngưỡng để kích hoạt trình thu gom rác có thể được sửa đổi bằng phương thức set_threshold[]

Ví dụ - 2

Trong ví dụ trên, giá trị của ngưỡng tăng cho cả ba thế hệ. Nó sẽ ảnh hưởng đến tần suất chạy bộ thu gom rác. Các lập trình viên không cần lo lắng về trình thu gom rác, nhưng nó đóng vai trò thiết yếu trong việc tối ưu hóa thời gian chạy Python cho hệ thống đích

Trình thu gom rác Python xử lý các chi tiết cấp thấp cho nhà phát triển

Tầm quan trọng của việc thực hiện thu gom rác thủ công

Như chúng ta đã thảo luận trước đó, trình thông dịch Python xử lý tham chiếu đến đối tượng được sử dụng trong chương trình. Nó tự động giải phóng bộ nhớ khi số tham chiếu bằng không. Đây là cách tiếp cận cổ điển để đếm tham chiếu, nếu nó không hoạt động khi chương trình có các chu kỳ tham chiếu. Chu kỳ tham chiếu xảy ra khi một hoặc nhiều đối tượng được tham chiếu với nhau. Do đó, số tham chiếu không bao giờ trở thành số không

Hãy hiểu ví dụ sau -

Chúng tôi đã tạo chu kỳ tham chiếu. Đối tượng list1 đang tham chiếu chính đối tượng list1. Khi hàm trả về đối tượng list1, bộ nhớ cho đối tượng list1 không được giải phóng. Vì vậy, việc đếm tham chiếu không phù hợp để giải chu trình tham chiếu. Tuy nhiên, chúng ta có thể giải quyết nó bằng cách thay đổi bộ thu gom rác hoặc hiệu suất của bộ thu gom rác

Để thực hiện điều đó, chúng tôi sẽ sử dụng gc. hàm coll[] cho mô-đun gc

Đoạn mã trên sẽ cung cấp số lượng đối tượng được thu thập và phân bổ lại

Chúng ta có thể thực hiện thu gom rác thủ công bằng hai phương pháp - thu gom rác dựa trên thời gian hoặc dựa trên sự kiện

các gc. Phương thức coll[] được sử dụng để thực hiện thu gom rác dựa trên thời gian. Phương thức này được gọi sau một khoảng thời gian cố định để thực hiện thu gom rác dựa trên thời gian

Trong bộ sưu tập rác dựa trên chẵn, gc. hàm coll[] gọi sau khi một sự kiện xảy ra. Hãy hiểu ví dụ sau

Ví dụ -

đầu ra

Here, we are creating garbage.. 
Collecting the object.. 
Number of unreachable objects collected by GC: 10 
Uncollectable garbage: []

Trong đoạn mã trên, chúng ta đã tạo đối tượng list1 được tham chiếu bởi biến danh sách. Phần tử đầu tiên của đối tượng danh sách đề cập đến chính nó. Số lượng tham chiếu của đối tượng danh sách luôn lớn hơn 0, ngay cả khi nó bị xóa hoặc nằm ngoài phạm vi của chương trình

Quản lý bộ nhớ C Python

Trong phần này, chúng ta sẽ thảo luận chi tiết về kiến ​​trúc bộ nhớ C Python

Như chúng ta đã thảo luận trước đó, có một lớp trừu tượng từ phần cứng vật lý đến Python. Nhiều ứng dụng hoặc Python truy cập vào bộ nhớ ảo được tạo bởi hệ điều hành

Python sử dụng một phần bộ nhớ để sử dụng nội bộ và bộ nhớ phi đối tượng. Một phần khác của bộ nhớ được sử dụng cho đối tượng Python như int, dict, list, v.v.

CPython chứa bộ cấp phát đối tượng cấp phát bộ nhớ trong vùng đối tượng. Bộ cấp phát đối tượng nhận được một cuộc gọi mỗi khi đối tượng mới cần không gian. Bộ cấp phát thiết kế chính cho lượng dữ liệu nhỏ vì Python không liên quan đến quá nhiều dữ liệu cùng một lúc. Nó cấp phát bộ nhớ khi thực sự cần thiết

Có ba thành phần chính của chiến lược cấp phát bộ nhớ CPython

Đấu trường - Đó là khối bộ nhớ lớn nhất và được căn chỉnh trên một ranh giới trang trong bộ nhớ. Hệ điều hành sử dụng ranh giới trang là cạnh của mâm cặp bộ nhớ liền kề có độ dài cố định. Python giả sử kích thước trang của hệ thống là 256 kilobyte

Pools - Nó bao gồm một lớp kích thước duy nhất. Một nhóm có cùng kích thước quản lý danh sách liên kết đôi. Một nhóm phải được sử dụng, đầy hoặc trống. Một nhóm đã sử dụng bao gồm các khối bộ nhớ để lưu trữ dữ liệu. Một nhóm đầy đủ có tất cả dữ liệu được phân bổ và chứa. Một nhóm trống không có bất kỳ dữ liệu nào và có thể được chỉ định bất kỳ loại kích thước nào cho khối khi cần

Khối - Nhóm chứa một con trỏ tới khối bộ nhớ "miễn phí" của chúng. Trong nhóm, có một con trỏ, cho biết khối bộ nhớ trống. Bộ cấp phát không chạm vào các khối này cho đến khi nó thực sự cần thiết

Các cách phổ biến để giảm độ phức tạp của không gian

Chúng ta có thể làm theo một số phương pháp hay nhất để giảm độ phức tạp của không gian. Những kỹ thuật này được cho là tiết kiệm khá nhiều không gian và làm cho chương trình hiệu quả. Dưới đây là một số thực hành trong Python dành cho bộ cấp phát bộ nhớ

Chúng tôi xác định một danh sách trong Python; . Giả sử chúng ta cần một danh sách con cho danh sách đã cho, sau đó chúng ta thực hiện cắt danh sách. Đó là một cách đơn giản để lấy danh sách con từ danh sách gốc. Bằng cách nào đó, nó phù hợp với lượng dữ liệu nhỏ nhưng không phù hợp với dữ liệu lớn

Do đó, việc cắt danh sách tạo ra các bản sao của đối tượng trong danh sách. Nó chỉ sao chép tham chiếu đến chúng. Do đó, bộ cấp phát bộ nhớ Python tạo một bản sao của đối tượng và cấp phát nó. Vì vậy, chúng ta cần tránh việc cắt danh sách

Cách tốt nhất để tránh việc nhà phát triển nên cố gắng sử dụng biến riêng biệt để theo dõi các chỉ số thay vì cắt một danh sách

  • Sử dụng danh sách lập chỉ mục một cách cẩn thận

Nhà phát triển nên cố gắng sử dụng "đối với mục trong mảng" thay vì "đối với chỉ mục trong phạm vi [len [mảng]]" để tiết kiệm không gian và thời gian. Nếu chương trình của chúng tôi không cần lập chỉ mục cho phần tử danh sách, thì đừng sử dụng nó

Nối chuỗi không phù hợp để tiết kiệm không gian và thời gian phức tạp. Khi có thể, chúng ta nên tránh sử dụng '+' để nối chuỗi vì chuỗi là bất biến. Khi chúng ta thêm chuỗi mới vào chuỗi hiện có, Python sẽ tạo chuỗi mới và phân bổ nó đến một địa chỉ mới

Mỗi chuỗi cần một kích thước bộ nhớ cố định dựa trên ký tự và độ dài của nó. Khi chúng tôi thay đổi chuỗi, nó cần một lượng bộ nhớ khác và yêu cầu phân bổ lại

Hãy chạy ví dụ sau

đầu ra

Nó sẽ tạo biến a để chỉ đối tượng chuỗi, là thông tin giá trị chuỗi

Sau đó, chúng tôi thêm sting mới vào đó bằng toán tử '+'. Python phân bổ lại chuỗi mới trong bộ nhớ dựa trên kích thước và độ dài của nó. Giả sử kích thước bộ nhớ của chuỗi ban đầu là n byte, thì chuỗi mới sẽ là m byte

Thay vì sử dụng nối chuỗi, chúng ta có thể sử dụng". tham gia [iterable_object]" hoặc định dạng hoặc%. Điều này ảnh hưởng rất lớn đến việc tiết kiệm bộ nhớ và thời gian

  • Sử dụng Iterator và Generator

Trình lặp rất hữu ích cho cả thời gian và bộ nhớ khi làm việc trên một tập dữ liệu lớn. Làm việc với tập dữ liệu lớn, chúng ta cần xử lý dữ liệu ngay lập tức và có thể đợi chương trình xử lý toàn bộ dữ liệu trước

Trình tạo là các hàm đặc biệt được sử dụng để tạo hàm lặp

Trong ví dụ sau, chúng tôi triển khai một trình vòng lặp gọi hàm tạo đặc biệt. Từ khóa suất trả về giá trị hiện tại, chỉ chuyển sang giá trị tiếp theo trong lần lặp tiếp theo của vòng lặp

Ví dụ -

  • Sử dụng Thư viện tích hợp khi có thể

Nếu chúng ta sử dụng các phương thức đã được xác định trước trong thư viện Python, thì hãy nhập thư viện tương ứng. Nó sẽ tiết kiệm rất nhiều không gian và thời gian. Chúng ta cũng có thể tạo một mô-đun để xác định chức năng và nhập nó vào chương trình làm việc hiện tại

Phần kết luận

Trong hướng dẫn này, chúng ta đã thảo luận về hoạt động của bộ nhớ trong Python. Chúng ta đã học cách Python quản lý bộ nhớ và cũng đã thảo luận về cách triển khai Python mặc định. CPython được viết bằng ngôn ngữ lập trình C. Python là một loại ngôn ngữ động sử dụng cấu trúc dữ liệu Heap để lưu trữ bộ nhớ

Làm cách nào để tính toán bộ nhớ trong Python?

Tất cả những gì bạn phải làm là thêm chức năng trang trí và chức năng process_memory trong mã của bạn và điều này sẽ cung cấp cho bạn bộ nhớ được tiêu thụ bởi .

Các loại bộ nhớ trong Python là gì?

Có hai loại cấp phát bộ nhớ trong Python, tĩnh và động. .
bộ nhớ tĩnh. Cấu trúc dữ liệu ngăn xếp cung cấp cấp phát bộ nhớ tĩnh, nghĩa là các biến nằm trong bộ nhớ ngăn xếp. .
bộ nhớ động

Python có sử dụng nhiều bộ nhớ không?

Những số đó có thể dễ dàng khớp với số nguyên 64 bit, vì vậy người ta hy vọng Python sẽ lưu trữ một triệu số nguyên đó trong không quá ~8MB. một triệu đối tượng 8 byte. Trên thực tế, Python sử dụng hơn 35 MB RAM để lưu trữ những con số này . Tại sao? .

Tại sao Python không hiệu quả về bộ nhớ?

Đó là cách cấp phát bộ nhớ chậm hơn . Khi bộ nhớ tĩnh được cấp phát, kích thước của nó không thể thay đổi và cũng không thể sử dụng lại. Do đó, kém hiệu quả. Chúng tôi có thể thay đổi kích thước bộ nhớ sau khi cấp phát và cũng có thể được sử dụng lại.

Chủ Đề