Python kiểm tra mức sử dụng bộ nhớ của dict

Trong bài đăng này, chúng tôi muốn đánh giá dung lượng bộ nhớ trong Python 3 của dữ liệu được lưu trữ ở các định dạng bảng khác nhau. Cụ thể, chúng tôi muốn so sánh DataFrames với các cấu trúc dữ liệu giống như JSON như Danh sách từ điển và Từ điển danh sách

Trên đây là 3 cách khác nhau để lưu trữ dữ liệu dạng bảng. Dữ liệu dạng bảng về cơ bản là dữ liệu được biểu thị bằng các hàng và cột. Trong kỳ thi này, chúng tôi sẽ bỏ qua bất kỳ câu hỏi nào liên quan đến hiệu quả đọc/ghi hoặc tra cứu. Chúng tôi hoàn toàn quan tâm đến một câu hỏi. cách tiếp cận nào sẽ giúp chúng ta tiết kiệm bộ nhớ nhất?

Tập dữ liệu #

Chúng tôi tạo một bộ dữ liệu thử nghiệm vô nghĩa [nhưng rất lớn] cho thử nghiệm này, sử dụng danh sách một số giống chó phổ biến. Danh sách này chắc chắn không thiên vị chút nào, và tất cả chúng chắc chắn là chó

Để đảm bảo rằng thử nghiệm đủ chung cho hầu hết các trường hợp sử dụng, chúng tôi đảm bảo rằng tập dữ liệu này có ít nhất ba loại dữ liệu nguyên thủy. str, int và float

thí nghiệm#

Chúng tôi chạy các phép tính đơn giản cho từng biến thể cấu trúc dữ liệu

Khung dữ liệu #

Việc đo bộ nhớ của DataFrames tương đối đơn giản và có thể được thực hiện bằng một chức năng tích hợp đơn giản. DataFrame.memory_usage

Điều này cho kết quả sau

84,613,093 B
84.61 MB

Danh sách từ điển#

Đo lường danh sách từ điển không đơn giản như trên

Để lấy kích thước của cấu trúc dữ liệu python gốc, chúng ta có thể sử dụng phương thức sys.getsizeof. Tuy nhiên, điều này chỉ cung cấp cho chúng ta kích thước [tính bằng byte] của chính đối tượng, mà không bao gồm kích thước của các phần tử lồng nhau của nó

Ví dụ: nếu một người có một danh sách các số nguyên [1, 2, 3], việc gọi sys.getsizeof[[1, 2, 3]] sẽ chỉ trả về kích thước của danh sách "trống", cùng với bộ nhớ được cấp phát của nó. Kích thước này sẽ không bao gồm các số nguyên 1, 2 hoặc 3. Bạn có thể tìm hiểu sâu về vấn đề này trong câu hỏi Stack Overflow rất nhiều thông tin này

Như vậy, người ta phải lặp lại từng đối tượng trong danh sách và từng cặp khóa-giá trị trong mỗi từ điển để có được kích thước tích lũy của cấu trúc dữ liệu

Điều này cho kết quả sau

515,041,877 B
515.04 MB

Từ điển danh sách #

Một cách khác để biểu diễn dữ liệu dạng bảng ở định dạng json là từ điển danh sách. Nó bao gồm một từ điển, trong đó mỗi khóa đại diện cho một cột và trỏ đến một mảng. Mỗi chỉ mục của mảng trong trường hợp như vậy tương ứng với chỉ mục hàng

một e. g. của cấu trúc dữ liệu như vậy như sau

{
    "breed": [ ... ],
    "count": [ ... ],
    "barks": [ ... ],
}

May mắn thay cho chúng tôi, chúng tôi không cần thực hiện bất kỳ thao tác phức tạp nào để đến cấu trúc dữ liệu trên. Thay vào đó, chúng tôi có thể sử dụng phương pháp to_dict do Pandas cung cấp trên DataFrame mà chúng tôi đã tạo trước đó, với tùy chọn đặc biệt orient=”list”

Điều này cho kết quả sau

136,593,711 B
136.59 MB

Phần kết luận#

Chúng ta có thể thấy rằng Pandas DataFrame, mặc dù có thêm độ phức tạp, nhưng có dung lượng nhỏ hơn đáng kể so với danh sách từ điển và thậm chí là từ điển danh sách. Cái sau lớn hơn khoảng 6 lần và 2 lần, tương ứng

Do đó, chúng tôi có thể kết luận rằng việc sử dụng DataFrames có thể là một tối ưu hóa không tầm thường hữu ích trong một số trường hợp sử dụng nhất định, đặc biệt khi dung lượng RAM là một vấn đề

Trong khi hầu hết sẽ nói sử dụng C hoặc C++ hoặc Rust hoặc C# hoặc Java. Tôi quyết định muốn xem xét các khía cạnh của hiệu năng Python và mức sử dụng bộ nhớ. Cụ thể, tôi bắt đầu tìm ra cách tiếp cận tốt nhất để xấp xỉ hiệu quả các cấu trúc hoặc lớp C thiên về thuộc tính hơn là chức năng

Tôi muốn tìm "lớp" hoặc từ điển Python3 nào hiệu quả nhất về bộ nhớ nhưng cũng nhanh để tạo, cập nhật và đọc một đối tượng. Tôi đã chọn xem xét những điều sau đây

  • Python dict [chế độ chờ cũ]
  • lớp Python
  • Lớp Python với __slots__ [ý tưởng này được thêm vào sau khi có đề xuất từ ​​một kỹ sư]
  • lớp dữ liệu
  • recordclass [vẫn là phiên bản beta]
  • NamedTuple một phần mở rộng của các bộ sưu tập

Cuối cùng, tôi đã mượn từ những ý chính này để tạo một số mã Python để kiểm tra tất cả những điều trên. Sau đó, tôi cũng tìm thấy chức năng "tổng kích thước" để ước tính kích thước của cấu trúc dữ liệu trong bộ nhớ từ ý chính này. Đây là mã để đo lường và kiểm tra hiệu suất và mức sử dụng bộ nhớ của Python

Bài kiểm tra liên quan đến những điều sau đây

  1. Tạo từ điển gồm 100.000 đối tượng cho mỗi "lớp" khác nhau
  2. Đọc từng giá trị mục nhập đối tượng
  3. Đọc thuộc tính con của mỗi mục nhập
  4. Đọc và làm phép tính nhỏ hai tính chất phụ
  5. Thực hiện thay đổi/ghi đè cấp cao nhất cho từng đối tượng
  6. Đọc thuộc tính thông qua phương thức lớp thay vì trực tiếp
  7. Thay đổi/ghi đè một thuộc tính thông qua một phương thức lớp thay vì trực tiếp
  8. Đo dung lượng bộ nhớ của từ điển đối tượng 100.000

Hiệu suất thô và kết quả kiểm tra bộ nhớ

Kết quả hiệu suất Python cho các cấu trúc dữ liệu khác nhauTestPython dictPython classPython class + slotsdataclassrecordclassNamedTuplecreates / sec369,377264,405354,373274,175418,359307,269reads / sec17,076,39424,402,51325,380,03121,8390,248,18,18

Nhìn chung, hiệu suất khá cao trên bảng. Tuy nhiên, việc tạo các đối tượng mới luôn chậm hơn trên tất cả các phương pháp. Không còn nghi ngờ gì nữa, điều này là do bộ nhớ phải được quản lý tại một số điểm. Thật đáng khích lệ khi thấy Python nói chung có thể quản lý hàng triệu lượt đọc và cập nhật mỗi giây trong một quy trình/luồng đơn. Rõ ràng là cách tiếp cận từ điển mặc định của chúng tôi thực sự có một số chi phí về bộ nhớ


Kết quả kiểm tra bộ nhớ và hiệu suất được chuẩn hóa để so sánh nhanh

Trực quan hóa với chuẩn hóa khối lượng yêu cầu của kết quả hiệu suất Python. TestPython dictPython classPython class + slotsdataclassrecordclassNamedTuplecreates/sec0. 880. 630. 850. 661. 000. 73lần đọc/giây0. 600. 860. 890. 761. 000. 87sub-reads/sec0. 800. 751. 000. 700. 820. 59đọc + calc / giây0. 970. 941. 000. 800. 880. 76thay đổi cấp cao nhất / sec0. 810. 741. 000. 780. 970. lớp 10 đọc / giây 1. 000. 810. 880. 800. 770. Cập nhật 70 lớp / giây1. 000. 410. 550. 460. 470. 08byte cho mỗi mục nhập [bộ nhớ]0. 230. 910. 870. 911. 000. 45

Chế độ xem này giúp so sánh nhanh tất cả các tùy chọn. Mỗi hàng được chuẩn hóa theo mục nhập tốt nhất trong hàng đó. Đọc hàng đầu tiên, lớp bản ghi là tốt nhất về số lần tạo mỗi giây trong khi các lớp Python hoạt động ở mức 63% hiệu suất của lớp bản ghi cho cùng số liệu tạo mỗi giây đó

Python dict sử dụng bao nhiêu bộ nhớ?

Nói cách khác, từ điển của chúng ta, không có gì trong đó, tiêu thụ 240 byte . Không tệ; .

Làm cách nào để kiểm tra mức sử dụng bộ nhớ trong Python?

Làm việc với Python Memory Profiler . Bạn sẽ thấy mức sử dụng bộ nhớ theo từng dòng sau khi tập lệnh của bạn thoát. putting the @profile decorator around any function or method and running python -m memory_profiler myscript. You'll see line-by-line memory usage once your script exits.

Có == cho dict trong Python không?

Theo tài liệu python, bạn thực sự có thể sử dụng toán tử == trên từ điển .

Từ điển sử dụng bao nhiêu bộ nhớ?

Mỗi chữ cái thường chiếm 1 byte. Điều đó có nghĩa là bạn cần khoảng 1 MB bộ nhớ để lưu toàn bộ từ điển. Tất nhiên bạn có thể xì hơi [zip] và lưu trữ trong bộ nhớ, với tỷ lệ nén khoảng 90%.

Chủ Đề