Byte riêng, byte ảo, tập làm việc là gì?


491

Tôi đang cố gắng sử dụng tiện ích perfmon windows để gỡ lỗi rò rỉ bộ nhớ trong một tiến trình.

Đây là cách perfmon giải thích các điều khoản:

Bộ làm việc là kích thước hiện tại, tính bằng byte, của Bộ làm việc của quy trình này. Bộ làm việc là tập hợp các trang bộ nhớ được chạm vào gần đây bởi các luồng trong quy trình. Nếu bộ nhớ trống trong máy tính vượt quá ngưỡng, các trang sẽ được để lại trong Bộ làm việc của một quy trình ngay cả khi chúng không được sử dụng. Khi bộ nhớ trống giảm xuống dưới ngưỡng, các trang sẽ được cắt bớt khỏi Bộ làm việc. Nếu cần, sau đó chúng sẽ bị lỗi mềm trở lại Bộ làm việc trước khi rời bộ nhớ chính.

Byte ảo là kích thước hiện tại, tính bằng byte, của không gian địa chỉ ảo mà quá trình đang sử dụng. Việc sử dụng không gian địa chỉ ảo không nhất thiết ngụ ý việc sử dụng tương ứng của các trang đĩa hoặc bộ nhớ chính. Không gian ảo là hữu hạn và quá trình có thể giới hạn khả năng tải các thư viện.

Byte riêng là kích thước hiện tại, tính bằng byte, của bộ nhớ mà quá trình này đã phân bổ không thể chia sẻ với các quy trình khác.

Đây là những câu hỏi tôi có:

Đây có phải là byte riêng mà tôi nên đo để chắc chắn liệu quy trình có bị rò rỉ hay không vì nó không liên quan đến bất kỳ thư viện dùng chung nào và bất kỳ rò rỉ nào, nếu xảy ra, sẽ đến từ chính quá trình đó?

Tổng bộ nhớ tiêu thụ của quá trình là gì? Đây có phải là byte ảo hay là tổng của byte ảo và bộ làm việc?

Có bất kỳ mối quan hệ nào giữa các byte riêng, bộ làm việc và byte ảo không?

Có công cụ nào khác cho ý tưởng tốt hơn về việc sử dụng bộ nhớ không?


3
Một công cụ tốt hơn sẽ là valgrind / helgrind, nhưng không may mắn trong Windows :(
Kornel Kisielewicz

Tôi có nên đo byte riêng để đảm bảo nếu quá trình có bất kỳ rò rỉ nào không Nếu các byte riêng của một tiến trình không phát triển thì bạn không bị rò rỉ bộ nhớ. Nếu chúng phát triển có thể là do rò rỉ bộ nhớ và có thể là do sự phân mảnh bộ nhớ. Tôi nghĩ thật khó để nói rằng nhìn vào sự tăng trưởng của các byte riêng tư nghĩa là gì.

@SergeiKurenkov Một điều chúng ta có thể nói là KHÔNG BAO GIỜ là do "sự phân mảnh bộ nhớ".
Jamie Hanrahan

Câu trả lời:


517

Câu trả lời ngắn gọn cho câu hỏi này là không có giá trị nào trong số này là một chỉ số đáng tin cậy về việc bộ nhớ thực sự sử dụng được bao nhiêu bộ nhớ và không có giá trị nào thực sự thích hợp để gỡ lỗi rò rỉ bộ nhớ.

Byte riêng đề cập đến dung lượng bộ nhớ mà quá trình thực thi đã yêu cầu - không nhất thiết là số lượng mà nó thực sự đang sử dụng . Chúng là "riêng tư" vì chúng (thường) loại trừ các tệp ánh xạ bộ nhớ (tức là các DLL được chia sẻ). Nhưng - đây là cách bắt - họ không nhất thiết loại trừ bộ nhớ được cấp phát bởi các tệp đó . Không có cách nào để biết liệu một sự thay đổi trong các byte riêng là do chính nó có thể thực thi được hay do một thư viện được liên kết. Các byte riêng tư cũng không chỉ là bộ nhớ vật lý; chúng có thể được phân trang vào đĩa hoặc trong danh sách trang chờ (nghĩa là không còn được sử dụng, nhưng chưa được phân trang).

Bộ công việc đề cập đến tổng bộ nhớ vật lý (RAM) được sử dụng bởi quy trình. Tuy nhiên, không giống như các byte riêng tư, điều này cũng bao gồm các tệp được ánh xạ bộ nhớ và các tài nguyên khác, do đó, nó là một phép đo thậm chí còn kém chính xác hơn các byte riêng tư. Đây là cùng một giá trị được báo cáo trong "Sử dụng Mem" của Trình quản lý tác vụ và là nguồn gốc của vô số sự nhầm lẫn trong những năm gần đây. Bộ nhớ trong Bộ làm việc là "vật lý" theo nghĩa là nó có thể được xử lý mà không có lỗi trang; Tuy nhiên, danh sách trang standby là cũng vẫn thể chất trong bộ nhớ nhưng không được báo cáo trong Set Working, và đây là lý do tại sao bạn có thể thấy "Mem Usage" đột nhiên thả khi bạn hạn chế tối đa một ứng dụng.

Byte ảo là tổng không gian địa chỉ ảo bị chiếm bởi toàn bộ quá trình. Điều này giống như tập làm việc, theo nghĩa là nó bao gồm các tệp ánh xạ bộ nhớ (DLL chung), nhưng nó cũng bao gồm dữ liệu trong danh sách chờ và dữ liệu đã được phân trang và đang nằm trong một trang trên đĩa ở đâu đó. Tổng số byte ảo được sử dụng bởi mọi quy trình trên một hệ thống chịu tải nặng sẽ tăng thêm bộ nhớ đáng kể so với máy thực sự có.

Vì vậy, các mối quan hệ là:

  • Byte riêng là những gì ứng dụng của bạn đã thực sự phân bổ, nhưng bao gồm việc sử dụng pagefile;
  • Bộ công việc là các byte riêng không phân trang cộng với các tệp ánh xạ bộ nhớ;
  • Byte ảo là Bộ làm việc cộng với byte riêng được phân trang và danh sách chờ.

Có một vấn đề khác ở đây; cũng giống như các thư viện dùng chung có thể phân bổ bộ nhớ trong mô-đun ứng dụng của bạn, dẫn đến các lỗi tích cực tiềm ẩn được báo cáo trong Private Byte của ứng dụng, ứng dụng của bạn cũng có thể phân bổ bộ nhớ trong các mô-đun được chia sẻ , dẫn đến phủ định sai . Điều đó có nghĩa là ứng dụng của bạn thực sự có thể bị rò rỉ bộ nhớ mà không bao giờ xuất hiện trong byte riêng tư. Không thể, nhưng có thể.

Byte riêng là một xấp xỉ hợp lý của lượng bộ nhớ mà bạn có thể sử dụng và có thể được sử dụng để thu hẹp danh sách các ứng cử viên tiềm năng bị rò rỉ bộ nhớ; nếu bạn thấy con số tăng lên và tăng trưởng liên tục và vô tận, bạn sẽ muốn kiểm tra xem có bị rò rỉ không. Tuy nhiên, điều này không thể chứng minh rằng có hoặc không có rò rỉ.

Một trong những công cụ hiệu quả nhất để phát hiện / sửa lỗi rò rỉ bộ nhớ trong Windows thực sự là Visual Studio (liên kết đến trang sử dụng VS để rò rỉ bộ nhớ, không phải trang sản phẩm). Rational Purify là một khả năng khác. Microsoft cũng có một tài liệu thực hành tốt nhất chung hơn về chủ đề này. Có nhiều công cụ được liệt kê trong câu hỏi trước đây .

Tôi hy vọng điều này sẽ làm sáng tỏ một vài điều! Theo dõi rò rỉ bộ nhớ là một trong những điều khó thực hiện nhất trong việc gỡ lỗi. Chúc may mắn.


26
Tôi sợ rằng bạn trả lời không hoàn toàn chính xác. Byte riêng đề cập đến dung lượng bộ nhớ (RAM) mà quá trình thực thi đã yêu cầu - không chỉ bộ nhớ vật lý. Do đó, bạn chắc chắn có thể kiểm tra hầu hết các trường hợp rò rỉ bộ nhớ bằng cách theo dõi các byte riêng. Hãy thử :: VisualAlloc để tạo ra một khối lớn bộ nhớ (giả sử 1,5G). Bạn sẽ có thể thấy rằng các byte riêng tư của bạn lớn hơn bộ làm việc. Điều đó chứng tỏ rằng "Bộ làm việc của bạn là byte riêng tư cộng với các tệp được ánh xạ bộ nhớ" là không chính xác.
Jay Zhu

4
Trên thực tế, tôi tin rằng sự hiểu biết ghi là "Bộ làm việc là byte riêng trong bộ nhớ cộng với các tệp được ánh xạ bộ nhớ". Và byte riêng tư có thể được hoán đổi - bạn có thể thấy các byte riêng lớn hơn bộ nhớ vật lý bạn có trong máy.
Jay Zhu

2
@Aaronaught: Tuyên bố đầu tiên của bạn về chỉ báo đáng tin cậy và thích hợp để gỡ lỗi là khó hiểu. Các byte riêng là một chỉ báo đáng tin cậy về sự rò rỉ không gian bộ nhớ ứng dụng. Nó có thể là một DLL phụ thuộc và gián tiếp nhưng nó là một rò rỉ trong không gian bộ nhớ ứng dụng. Bạn có thể giải thích tại sao nó không thể được sử dụng để gỡ lỗi? kết xuất bộ nhớ đầy đủ của quá trình ứng dụng sẽ cho chúng ta biết những gì đang tiêu thụ bộ nhớ này. Tôi không chắc chắn tôi hiểu tại sao nó không thể được sử dụng để gỡ lỗi. Bạn có thể làm sáng tỏ?
G33kKahuna

@ G33kKahuna: Tôi không rõ làm thế nào một kết xuất bộ nhớ sẽ cho bạn biết những gì đang tiêu thụ bộ nhớ theo bất kỳ ý nghĩa nào - trừ khi "bạn" nghĩa là gì "mô-đun", nhưng sau đó tất cả những gì bạn có là một ảnh chụp nhanh, bạn vẫn không thể nhìn thấy mô-đun nào thực sự rò rỉ bộ nhớ theo thời gian trừ khi bạn mất nhiều lần theo thời gian và trong các điều kiện kiểm soát chặt chẽ. Thật khó để nghĩ ra một chiến lược gỡ lỗi không hiệu quả và không đáng tin cậy hơn. Hồ sơ ở khắp mọi nơi những ngày này; sử dụng một.
Aaronaught

1
Chạy đầy đủ! Objsize, điều này sẽ hiển thị bất kỳ đối tượng được ghim trong đống ngay lập tức. Bạn có thể xác nhận bằng cách kiểm tra eeheap -gc. Điều này sẽ cho bạn thấy nơi âm lượng bị mắc kẹt. Thông thường, nếu không có gợi ý nào có sẵn với tất cả các lệnh trên, các byte riêng tư của bạn sẽ bị tiêu thụ bởi các đối tượng không bị thu thập trong GC. Bây giờ chuyển sang một trong hai hàng hóa hoặc gcleaks. Các lệnh này sẽ cho bạn biết những loại / địa chỉ đối tượng không thể được ánh xạ. Con trỏ vẫn còn nhưng đối tượng đã biến mất. Đây là vấn đề phân loại như vậy cho xử lý sự kiện chưa phát hành.
G33kKahuna

10

Bạn không nên cố gắng sử dụng perfmon, trình quản lý tác vụ hoặc bất kỳ công cụ nào như thế để xác định rò rỉ bộ nhớ. Chúng tốt cho việc xác định xu hướng, nhưng không nhiều. Các số họ báo cáo theo thuật ngữ tuyệt đối quá mơ hồ và được tổng hợp để hữu ích cho một tác vụ cụ thể như phát hiện rò rỉ bộ nhớ.

Một câu trả lời trước cho câu hỏi này đã đưa ra một lời giải thích tuyệt vời về các loại khác nhau là gì.

Bạn hỏi về một đề xuất công cụ: Tôi khuyên bạn nên Trình xác thực bộ nhớ. Có khả năng giám sát các ứng dụng tạo ra hàng tỷ phân bổ bộ nhớ.

http://www.softwareverify.com/cpp/memory/index.html

Tuyên bố miễn trừ trách nhiệm: Tôi đã thiết kế Trình xác thực bộ nhớ.


1
Tôi thậm chí không thể chạy một tệp lớp đơn giản (bằng Java)? Đưa cái gì?
jn1kk

Tôi nghi ngờ rằng Stephen và Devil có liên quan đến nhau hoặc thậm chí được nhân bản ...: D;)
Robert Koritnik

@StephenKellett, Có phiên bản dùng thử không?
Pacerier

@Pacerier nếu bạn theo liên kết, có bản dùng thử cho cả phiên bản x86 và x64 ngay phía trên tùy chọn mua ở bên trái của trang.
Bradley A. Tetreault

10

Định nghĩa của bộ đếm perfmon đã bị phá vỡ ngay từ đầu và vì một lý do nào đó dường như quá khó để sửa.

Tổng quan tốt về quản lý bộ nhớ Windows có sẵn trong video " Bí ẩn về quản lý bộ nhớ được tiết lộ " trên MSDN: Nó bao gồm nhiều chủ đề hơn mức cần thiết để theo dõi rò rỉ bộ nhớ (ví dụ: quản lý bộ làm việc) nhưng cung cấp đủ chi tiết trong các chủ đề có liên quan.


Để cung cấp cho bạn một gợi ý về vấn đề với các mô tả bộ đếm perfmon, đây là câu chuyện bên trong về các byte riêng tư từ " Bộ đếm hiệu suất byte riêng tư - Hãy coi chừng! " Trên MSDN:

Q: Khi nào thì Byte riêng không phải là Byte riêng?

A: Khi nó không cư trú.

Bộ đếm Byte riêng báo cáo phí cam kết của quy trình. Điều đó có nghĩa là, dung lượng đã được phân bổ trong tệp hoán đổi để giữ nội dung của bộ nhớ riêng trong trường hợp nó bị tráo đổi. Lưu ý: Tôi đang tránh từ "dành riêng" vì có thể nhầm lẫn với bộ nhớ ảo ở trạng thái dành riêng không được cam kết.


Từ " Lập kế hoạch hiệu suất " trên MSDN:

3.3 byte riêng

3.3.1 Mô tả

Bộ nhớ riêng, được định nghĩa là bộ nhớ được phân bổ cho một quy trình không thể chia sẻ bởi các quy trình khác. Bộ nhớ này đắt hơn bộ nhớ dùng chung khi nhiều quá trình như vậy thực thi trên một máy. Bộ nhớ riêng trong các dll không được quản lý (truyền thống) thường tạo thành các thống kê C ++ và chiếm 5% tổng số tập làm việc của dll.


1
bỏ phiếu vì những ví dụ cực kỳ hay về việc nó bị hỏng như thế nào!
Bruno Brant

Trích dẫn đầu tiên là sai. Phân bổ "byte riêng tư" không yêu cầu bất cứ điều gì được "phân bổ trong tệp hoán đổi" (cái thực sự được gọi là pagefile). Bạn thậm chí không phải có một tệp trang để "byte riêng" được phân bổ. Trong thực tế, việc phân bổ các byte riêng không sử dụng ngay lập tức bất kỳ không gian nào ở bất kỳ đâu và có thể không bao giờ sử dụng nhiều như đã được phân bổ.
Jamie Hanrahan

Trích dẫn thứ hai không tốt hơn nhiều. Các byte riêng được sử dụng trong mã DLL không nhất thiết phải được phân bổ tĩnh trong DLL. Mã DLL hoàn toàn miễn phí khi gọi VirtualAlloc, HeapAlloc (malloc và mới trong CRTL), v.v. Nó cũng cố gắng mô tả kích thước bộ nhớ riêng dưới dạng phần trăm của kích thước bộ làm việc, là vô nghĩa. Cái trước là kích thước ảo (và sẽ giống nhau cho mỗi lần sử dụng mã có cùng đầu vào) trong khi cái sau là vật lý (có thể hoàn toàn khác nhau từ lần chạy này đến lần chạy tiếp theo, tùy thuộc vào mức độ giàu bộ nhớ hoặc - bỏ đói máy là).
Jamie Hanrahan

5

Có một cuộc thảo luận thú vị ở đây: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Sự hiểu biết của tôi về chủ đề này là giải phóng phân bổ nhỏ không được phản ánh trong Private Byte hoặc Work Set.

Mẩu chuyện dài:

nếu tôi gọi

p=malloc(1000);
free(p);

sau đó các byte riêng chỉ phản ánh sự phân bổ, không phải là sự phân bổ.

nếu tôi gọi

p=malloc(>512k);
free(p);

sau đó các byte riêng phản ánh chính xác sự phân bổ và sự phân bổ.


7
Điều này được giải thích là do các hàm bộ nhớ thư viện chuẩn C sử dụng tùy chỉnh hoặc Win32 Heap, là một cơ chế quản lý bộ nhớ nằm trên quản lý bộ nhớ cấp quy trình cấp thấp.
Kyberias

@Kyberias, vậy làm thế nào để chúng ta có được dưới đó?
Pacerier

trong khi (1) miễn phí (malloc (1000)); // Điều này có khiến byte riêng tăng lên mãi mãi không?
franckspike

2
@franckspike: không, nó sẽ tăng đến một điểm nhất định (thường là khoảng 4 kB, nhưng điều này có thể thay đổi) và sau đó dừng lại, vì CRT sẽ sử dụng lại bộ nhớ đã giải phóng trước đó thay vì yêu cầu các trang mới từ HĐH.
Miral

@Pacerier: Bạn có thể gọi Virtual ALLoc và VirtualFree.
Jamie Hanrahan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.