"Mức dùng bộ nhớ" của Windows thực sự nghĩa là gì? — Đọc đúng Working Set, Private Bytes, Commit và tệp trang
· Go Komura · Windows, Phát triển Windows, Quản lý bộ nhớ, Working Set, Private Bytes, Commit, Tệp trang, Giám sát hiệu năng, Khắc phục sự cố, Sysinternals
Task Manager hiện “Memory” của một tiến trình là 1,2GB. Thế mà Process Explorer hiện Working Set 1,5GB và Private Bytes 2,4GB, và Size của VMMap còn lớn hơn. Nhìn cả hệ thống, đọc “Committed 19,6/31,8GB”.
Vậy cuối cùng ứng dụng này thực sự dùng bao nhiêu gigabyte bộ nhớ?
Câu trả lời là con số bạn nên nhìn tùy vào điều bạn thực sự muốn biết. Chỉ số dùng khác nhau tùy bạn muốn biết lượng hiện trú trong RAM, lượng được cấp riêng cho tiến trình đó, lượng hệ thống đã hứa sẽ tiếp tục chống đỡ, hay chỉ dải địa chỉ ảo đã được đặt chỗ.
Điều làm các chỉ số bộ nhớ Windows rối là chúng đều hiện dưới cùng một từ “bộ nhớ”, dù thực ra đo các trục tách biệt sau.
- Bao nhiêu không gian địa chỉ đang dùng
- Bao nhiêu commit đã tiêu
- Hiện có trú trong RAM vật lý không
- Trang đó riêng của tiến trình, hay dùng chung được
- Cả hệ thống còn chống đỡ được bao nhiêu cấp phát nữa
Bài viết này dành cho ai đang điều tra bộ nhớ ứng dụng tăng hoặc thiếu bộ nhớ toàn hệ thống trên Windows 10/11 và Windows Server hiện tại, và nối, trong một bức tranh, quan hệ giữa Working Set, Private Working Set, Private Bytes, Commit, Virtual Bytes, tệp trang, Available và lỗi trang.
Quy trình lần ra vì sao đối tượng .NET không được thu thập được trình bày chi tiết trong “Phân biệt độ trễ GC với rò rỉ bộ nhớ trong .NET”, và thao tác cụ thể của VMMap cùng Process Explorer nằm trong “Process Explorer / Handle / VMMap trong thực tiễn”. Bài này tập trung vào điều kiện tiên quyết của cả hai: cách đọc các con số phía hệ điều hành Windows.
1. Kết luận trước
- Working Set là tập trang hiện trú trong RAM. Nó gồm không chỉ trang riêng của tiến trình mà cả trang có thể dùng chung với tiến trình khác, như mã DLL và tệp ánh xạ bộ nhớ.1
- Private Working Set là phần Working Set hiện chỉ thuộc tiến trình đó. Hữu ích như ước lượng “RAM mà tiến trình này một mình đang chiếm”, nhưng không phải tổng lượng ứng dụng đã cấp phát.2
- Private Bytes là lượng commit riêng của tiến trình đó. Đây là chỉ số tách khỏi việc bộ nhớ hiện có trú trong RAM hay không. Trường
PagefileUsagetrong cấu trúc API Win32 cũng, trên Windows hiện tại, về hiệu quả biểu diễn cùng Commit Charge, chứ không phải số byte thực sự ghi vào tệp trang.2 - “Committed X/Y” của Task Manager hiện X là tổng commit hiện tại của hệ thống và Y là trần commit. X không phải mức dùng tệp trang. Y được quyết đại thể bởi RAM cộng tệp trang.3
- Reserve và Commit là hai việc khác. Chỉ đặt chỗ một dải địa chỉ ảo chỉ dành dải đó cho dùng sau; nó không tiêu cùng lượng RAM hay trần commit.45
- Lỗi trang không nhất thiết nghĩa là I/O đĩa. Có lỗi mềm, giải được trong RAM, và lỗi cứng, đọc từ tệp trang, tệp thực thi, tệp ánh xạ bộ nhớ và tương tự.16
- Rò rỉ bộ nhớ được phán không từ một lần đọc mà từ xu hướng khi cùng tải được lặp. Đặc biệt, xem Private Bytes và phần tách có tiếp tục leo từng bậc sau khi xử lý xong, mà không trở về cùng trạng thái ổn định.
Một câu: Working Set là “lượng hiện trong RAM”, Private Bytes là “lượng được hứa riêng cho tiến trình này”, và Commit là “lượng cả hệ thống đã hứa”.
flowchart TB
accTitle: Chọn đúng chỉ số bộ nhớ Windows
accDescr: Chỉ số cần xem tùy bạn muốn biết trú RAM, commit riêng tiến trình, commit toàn hệ thống, hay dải địa chỉ ảo
question["Bạn muốn biết gì về mức dùng bộ nhớ"]
question -->|lượng hiện trong RAM| workingSet["Working Set"]
question -->|lượng được hứa riêng tiến trình| privateBytes["Private Bytes"]
question -->|lượng được hứa toàn hệ thống| systemCommit["System Commit"]
question -->|dải địa chỉ đã đặt chỗ| virtualBytes["Virtual Bytes / Reserved"]
workingSet --> resident["Trú trong RAM vật lý"]
privateBytes --> privateCommit["Commit riêng tiến trình"]
systemCommit --> commitLimit["So với Commit Limit"]
virtualBytes --> addressSpace["Không gian địa chỉ ảo"]
Hình 1: Tách quan sát “bộ nhớ cao” thành bốn câu hỏi riêng trước.
2. Tách “mức dùng bộ nhớ” thành bốn trục
Để bắt đầu, nghĩ bộ nhớ Windows không như “một thanh” mà theo bốn trục.
flowchart TB
accTitle: Bốn trục độc lập để phân loại một trang
accDescr: Kiểm trạng thái địa chỉ ảo, phần chống đỡ của trang đã commit, trú trong RAM vật lý, và khả năng dùng chung với tiến trình khác, tách nhau
page["Nhìn một trang theo bốn trục"]
page --> address["Trạng thái địa chỉ"]
address --> addressValues["Free / Reserved / Committed"]
page --> backing["Phần chống đỡ"]
backing --> backingValues["Page-file-backed / File-backed"]
page --> residentAxis["Trú RAM"]
residentAxis --> residentValues["Resident / Not resident"]
page --> sharing["Khả năng dùng chung"]
sharing --> sharingValues["Private / Shareable"]
Hình 2: Ngay với một trang, trạng thái địa chỉ, phần chống đỡ, trú, và khả năng dùng chung mỗi cái được quyết độc lập.
Mapped không phải trạng thái địa chỉ cạnh Free, Reserved và Committed — nó là một hạng vùng. Trang trong một view đã ánh xạ cũng có thể Committed. Cũng vậy, Private không phải phương tiện chống đỡ mà là phân loại khả năng dùng chung. Vậy hãy đọc phần chống đỡ là Page-file-backed hoặc File-backed, và khả năng dùng chung là Private hoặc Shareable, tách nhau.
Ghép bốn trục này cho quan hệ giữa các chỉ số đại diện như sau.
| Trạng thái trang | Working Set | Private Working Set | Private Bytes | Họ Virtual Bytes |
|---|---|---|---|---|
| Riêng tiến trình, đã commit, trú RAM | Gồm | Gồm | Gồm | Gồm |
| Riêng tiến trình, đã commit, không trú RAM | Không gồm | Không gồm | Gồm | Gồm |
| Trang dùng chung của DLL hoặc tệp ánh xạ, trú RAM | Gồm | Thường không gồm | Thường không gồm | Gồm |
| Đã đặt chỗ nhưng chưa commit | Không gồm | Không gồm | Không gồm | Có thể gồm |
| Dải địa chỉ chưa dùng | Không gồm | Không gồm | Không gồm | Thường không gồm |
flowchart TB
accTitle: Ánh xạ loại trang tới các chỉ số bộ nhớ chính
accDescr: Cho thấy chỉ số nào gồm trang riêng đang trú, trang riêng không trú, trang dùng chung đang trú, và dải chỉ đặt chỗ
privateResident["Riêng, đã commit, trú RAM"]
privateNonresident["Riêng, đã commit, không trú RAM"]
sharedResident["Trang dùng chung, trú RAM"]
reservedOnly["Đã đặt chỗ, chưa commit"]
workingSet["Working Set"]
privateWorkingSet["Private Working Set"]
privateBytes["Private Bytes"]
virtualBytes["Họ Virtual Bytes"]
privateResident --> workingSet
privateResident --> privateWorkingSet
privateResident --> privateBytes
privateResident --> virtualBytes
privateNonresident --> privateBytes
privateNonresident --> virtualBytes
sharedResident --> workingSet
sharedResident --> virtualBytes
reservedOnly --> virtualBytes
Hình 3: Working Set và Private Bytes đếm các tập trang khác nhau, nên chúng không ở quan hệ chứa đơn giản.
Điểm quan trọng ở đây là Working Set và Private Bytes không ở quan hệ chứa đơn giản.
Private Bytes gồm các trang riêng của tiến trình nhưng hiện không trú trong RAM. Working Set, ngược lại, gồm các trang dùng chung — như mã DLL và bộ nhớ dùng chung — mà Private Bytes không đếm chút nào. Vậy tùy tiến trình và thời điểm, Working Set có thể lớn hơn Private Bytes, hoặc ngược lại.
Cũng vậy, chỉ cộng Working Set của nhiều tiến trình có thể đếm cùng một trang vật lý — như DLL dùng chung — hơn một lần. “Tổng Working Set mỗi tiến trình bằng RAM đang dùng” không nhất thiết đúng.
3. Không gian địa chỉ ảo — Reserve và Commit là hai việc khác
3.1. Địa chỉ ảo không phải địa chỉ RAM vật lý
Mỗi tiến trình có không gian địa chỉ ảo riêng. Con trỏ ứng dụng làm việc không trực tiếp chỉ vị trí trong RAM vật lý; Windows dùng bảng trang để ánh xạ địa chỉ ảo tới trang vật lý hoặc dữ liệu trên tệp.7
Kết quả là, ngay trên PC gắn 64GB RAM, không gian địa chỉ ảo một tiến trình 32-bit dùng được thường nhỏ hơn nhiều. Ngược lại, tiến trình 64-bit có không gian địa chỉ ảo lớn hơn RAM vật lý cũng là chuyện thường.
3.2. Reserved chỉ nghĩa “đã cắm địa chỉ”
MEM_RESERVE của VirtualAlloc đặt chỗ một dải địa chỉ ảo liên tục để dùng sau. Ở giai đoạn này không có lưu trữ vật lý gắn với các trang, và dải đó không đọc hay ghi được.45
Ví dụ, dù cơ sở dữ liệu hay runtime Reserve một dải địa chỉ 8GB cho tăng trưởng sau, chỉ thế không tiêu 8GB RAM hay 8GB Private Bytes.
3.3. Committed là lời hứa “sẽ chống khi cần”
MEM_COMMIT là thao tác đưa trang ảo vào trạng thái Committed và bắt Windows hứa cung cấp phần chống đỡ cần thiết. Việc đọc, ghi hay thực thi thực sự được phép được quyết tách bởi bảo vệ trang — PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE, PAGE_NOACCESS và tương tự — nên bản thân Committed không nghĩa “đọc ghi được”. Lúc commit nó được tính vào Commit Charge hệ thống, nhưng trang vật lý thực có thể chưa được gán đến lần truy cập đầu. Một trang chạm lần đầu được khởi tạo zero, đi qua demand-zero fault, rồi vào Working Set.51
Vậy dù gọi là “đã cấp phát” cả hai cách, thực ra có ba giai đoạn sau.
flowchart TB
accTitle: Ba giai đoạn từ Reserve qua Commit tới trú RAM
accDescr: Cho thấy luồng đặt chỗ địa chỉ ảo, commit trang, và lần truy cập đầu gán trang vật lý rồi vào Working Set
reserve["MEM_RESERVE - đặt chỗ dải địa chỉ"]
reserve -.-> virtualMetric["Phản ánh ở họ Virtual Bytes"]
reserve -->|MEM_COMMIT| committed["Committed - truy cập được theo bảo vệ trang"]
committed -.-> commitMetric["Phản ánh ở Private Bytes / System Commit"]
committed -->|lần truy cập đầu, demand-zero fault| resident["Gán trang vật lý, trú RAM"]
resident -.-> workingSetMetric["Phản ánh ở Working Set"]
committed -.->|nếu không bao giờ truy cập| nonresident["Đã commit nhưng không trú"]
Hình 4: Reserve, Commit và lần truy cập đầu là các sự kiện tách, và mỗi cái dịch một chỉ số khác.
Ba giai đoạn này dịch các con số của họ Virtual Bytes, Private Bytes và Working Set tách nhau.
3.4. Vì sao vẫn OutOfMemory dù còn RAM trống
Cấp phát bộ nhớ thành công không được quyết chỉ bởi RAM trống.
- Tiến trình đã hết không gian địa chỉ ảo
- Không có dải địa chỉ trống kích thước cần liên tục
- Commit Charge toàn hệ thống đã tới Commit Limit
- Job Object, container, runtime hoặc thư viện có giới hạn riêng
- Đó là tiến trình 32-bit
- Heap gốc bị phân mảnh
Ngay trên Windows 64-bit, không gian địa chỉ ảo chế độ người dùng của tiến trình 32-bit thường là 2GB nếu IMAGE_FILE_LARGE_ADDRESS_AWARE không được đặt. Ứng dụng 32-bit có cờ đó dùng được tới 4GB trên Windows 64-bit.8
Vậy “PC còn 20GB RAM trống, thế mà ứng dụng 32-bit thất bại quanh 1,6GB” không mâu thuẫn. Có thể chẳng phải vấn đề RAM, mà là phân mảnh không gian địa chỉ hoặc chạm giới hạn cứng.
4. Working Set — các trang hiện trong RAM
Working Set là tập trang, trong không gian địa chỉ ảo của một tiến trình, hiện trú trong RAM vật lý.1
Tập này là hỗn hợp các thứ sau.
- Heap và ngăn xếp của chính tiến trình
- Mã và dữ liệu chỉ đọc của EXE cùng DLL
- Tệp ánh xạ bộ nhớ
- Bộ nhớ dùng chung
- Trang trở thành riêng của tiến trình đó sau copy-on-write
- Trang mà runtime và các thư viện đã chạm
4.1. Working Set tăng không nhất thiết nghĩa đã cấp phát thêm
Truy cập lần đầu một trang đã commit có thể tăng một mình Working Set trong khi Private Bytes đứng yên. Cũng vậy, khi một tệp lớn được ánh xạ bộ nhớ và đọc tuần tự, các trang chống bằng tệp vào Working Set trong khi Private Bytes hầu như không tăng.
Ngược lại, khi Windows Trim Working Set vì áp lực bộ nhớ, một mình Working Set co lại trong khi ứng dụng về logic vẫn giữ cùng bộ nhớ. Chạm lại sau đưa nó về qua lỗi trang.
Vậy Working Set giảm không nhất thiết nghĩa “ứng dụng đã giải phóng”, và tăng không nhất thiết nghĩa “ứng dụng vừa cấp phát mới”.
flowchart TB
accTitle: Luồng điển hình chỉ Working Set lên xuống
accDescr: Cùng một trang đã commit vào RAM ở lần truy cập đầu, trở thành không trú khi Trim, và trở lại khi truy cập lại, trong khi Private Bytes vẫn được đếm suốt
committed["Cùng trang đã commit"]
committed -->|lần truy cập đầu| resident["Trú RAM"]
resident -->|Trim dưới áp lực bộ nhớ| nonresident["Không trú"]
nonresident -->|lỗi trang khi truy cập lại| resident
resident -.-> inWorkingSet["Gồm trong Working Set"]
nonresident -.-> outsideWorkingSet["Không gồm trong Working Set"]
committed -.-> privateBytes["Được đếm ở Private Bytes khi còn commit"]
Hình 5: Working Set lên xuống theo trú, nhưng Private Bytes không giảm khi commit trên cùng trang còn.
4.2. Working Set gồm các trang dùng chung
Nếu 10 tiến trình dùng chung các trang mã của cùng một DLL, trang đó có thể hiện trong Working Set mỗi tiến trình, dù chỉ một bản tồn tại trong RAM vật lý. Tổng Working Set vượt RAM lắp đặt không lập tức là dấu hiệu sự cố.
Nếu muốn gần hơn “RAM mà tiến trình này một mình đang chiếm”, hãy nhìn Private Working Set. Dù vậy, đây cũng không phải “toàn bộ bộ nhớ tiến trình đó đã cấp phát” — nó chặt là các trang riêng hiện đang trú.
4.3. Ép Working Set xuống không sửa rò rỉ
Bạn có thể dùng EmptyWorkingSet hoặc SetProcessWorkingSetSize để đuổi trang khỏi Working Set của một tiến trình. Nhưng đây không phải thao tác giải phóng commit hay nhả tham chiếu trên heap. Mức dùng RAM bề ngoài giảm trong khi Private Bytes đứng yên, và lần truy cập tiếp có thể kích một loạt lỗi trang.9
Nếu con số Task Manager chỉ co ngay sau khi bạn bấm nút “giảm bộ nhớ”, rồi lập tức leo lại khi bạn làm việc tiếp, đó có thể chỉ là Trim Working Set chứ không phải “giải phóng” thật.
5. Private Bytes — lượng commit riêng của một tiến trình
Private Bytes là lượng bộ nhớ ảo đã commit riêng cho tiến trình đó. Nó biểu diễn Commit Charge không thể dùng chung với tiến trình khác, và không quan tâm hiện có trú trong RAM hay không. Trong PROCESS_MEMORY_COUNTERS_EX của Microsoft, PrivateUsage tương ứng giá trị này.102
API Win32 cũng có trường tên gây nhầm, PagefileUsage, nhưng tài liệu hiện tại định nghĩa nó là “Commit Charge của tiến trình đó” và nêu nó cùng giá trị với PrivateUsage. Nói cách khác, Private Bytes 2GB không nghĩa “2GB đã được ghi vào pagefile.sys”.2
Private Bytes thường bị ảnh hưởng bởi các thứ sau.
- Commit của heap gốc dùng bởi
HeapAlloc,malloc,newvà tương tự - Private Data commit trực tiếp bằng
VirtualAlloc - Vùng đã commit của heap GC .NET
- Phần ngăn xếp luồng thực sự đã commit
- Commit Charge cho cả view được đặt chỗ khi ánh xạ một view copy-on-write (
FILE_MAP_COPY) - Bộ đệm riêng mà thư viện và SDK thiết bị giữ bên trong
Trong view copy-on-write tạo bằng FILE_MAP_COPY, mỗi trang cuối cùng có thể trở thành riêng, nên lúc ánh xạ Windows đặt chỗ đủ Commit Charge để chống cả view bằng tệp trang. Vì thế, System Commit và Commit Charge của tiến trình (Private Bytes) có thể tăng bằng kích thước cả view ngay trước khi bất kỳ lần ghi nào thực sự tạo bản sao riêng.11
5.1. Vì sao Private Bytes không giảm sau free hoặc GC
Ngay khi bộ nhớ được “giải phóng” từ góc ứng dụng, runtime hoặc bộ cấp phát heap có thể không Decommit vùng đó về OS, mà giữ lại để dùng lại sau. Khi đó Private Bytes vẫn cao dù vùng đó dùng lại được bên trong ứng dụng.
Nó cũng có thể ở cao vì lý do như chỉ một phần vùng lớn còn sống, phân mảnh, hoặc bộ nhớ đệm hay pool đã nóng tới trần.
Vậy Private Bytes cao một mình không chứng rò rỉ. Điều bạn nên nhìn là so sánh theo thời gian:
- Lặp cùng xử lý cùng số lần
- Chờ cùng khoảng thời gian sau xử lý
- Kiểm Private Bytes có trở về cùng mức, hay nằm ngang ở một giá trị cố định
- Dùng VMMap hoặc dump heap để kiểm vùng hay kiểu nào đã lớn
flowchart TB
accTitle: Vì sao Private Bytes không giảm sau free hoặc GC
accDescr: Private Bytes đổi khác tùy bộ cấp phát có trả về OS vùng ứng dụng không còn cần, hay giữ lại để dùng lại
release["Ứng dụng giải phóng vùng qua free / GC"]
release --> decision{"Bộ cấp phát có trả về OS không"}
decision -->|Decommit / Release| returned["Commit Charge giảm"]
returned --> lower["Private Bytes giảm"]
decision -->|giữ lại để dùng lại| retained["Vùng vẫn commit"]
retained --> high["Private Bytes nằm ngang cao"]
retained --> reasons["Pool, bộ nhớ đệm, phân mảnh"]
Hình 6: Vùng trở thành dùng lại được trong ứng dụng không giống Commit của nó được trả về OS.
5.2. Mẫu ứng viên mạnh cho rò rỉ
Một tăng như sau, trong đó sàn leo lên mỗi vòng tải theo kiểu “bậc thang”, đáng chú ý.
Private Bytes
^
| ________
| ______|
| ______|
|_____|
+----------------------------> Lặp lại cùng xử lý
Dù vậy, ngay hình bậc thang cũng có thể chỉ vài vòng tăng từ JIT lần đầu, phông, bộ giải mã ảnh, pool kết nối, hoặc làm nóng bộ nhớ đệm, rồi ổn định. Điều quan trọng không phải rằng nó đang tăng, mà rằng nó không hội tụ về trạng thái ổn định.
6. System Commit — “Committed X/Y” thực sự là gì
Con số “Committed X/Y” trên tab [Performance] → [Memory] của Task Manager là chỉ số toàn hệ thống.
- X: System Commit Charge — bộ nhớ đã commit mà Windows hiện đang hứa sẽ chống trên cả hệ thống
- Y: System Commit Limit — trần commit hệ thống có thể chống
Commit Limit được quyết đại thể bởi RAM vật lý cộng tổng mọi tệp trang. Không có tệp trang, nó ra hơi nhỏ hơn RAM lắp đặt.36
flowchart TB
accTitle: Quan hệ giữa System Commit Charge và Commit Limit
accDescr: Commit từng tiến trình, phần dùng chung và kernel tạo giá trị hiện tại X, trong khi RAM vật lý và tệp trang chống trần Y
processCommit["Private Commit mỗi tiến trình"] --> charge["System Commit Charge - X"]
sharedCommit["Commit phần dùng chung chống bằng tệp trang"] --> charge
kernelCommit["Commit kernel"] --> charge
physicalRam["RAM vật lý"] --> limit["System Commit Limit - Y"]
pageFiles["Tệp trang"] --> limit
charge -->|X không vượt Y được| limit
Hình 7: X là lượng đang được hứa và Y là trần có thể chống lời hứa đó — đây không phải hiện mức dùng tệp trang.
System Commit Charge gồm không chỉ tổng Private Bytes mỗi tiến trình, mà cả Commit của các phần dùng chung chống bằng tệp trang và Commit kernel tiêu. Vậy tổng Private Bytes từng tiến trình một mình không giải thích hết X.
6.1. Commit Charge không phải mức dùng tệp trang
Xét một hệ thống 16GB RAM, tệp trang 16GB, và Committed ở 20/31GB.
20GB đó không nghĩa “20GB đã được ghi vào tệp trang”. Đó là tổng lượng Windows đang hứa sẽ cung cấp chống đỡ RAM hoặc tệp trang, khi cần, cho các trang riêng ghi được và tương tự.
Lúc đó, hỗn hợp các trạng thái sau có thể đúng:
- Phần lớn trú trong RAM
- Một phần đã được paging ra tệp trang
- Một phần đã commit nhưng chưa có lần truy cập đầu
- Một phần bị tiêu như commit phía kernel
Nếu muốn thấy mức dùng tệp trang thực, kiểm Paging File(*)\% Usage tách khỏi Commit. Ngay tài liệu của Microsoft cũng giải thích rằng mức dùng tệp trang cao một mình không nhất thiết chỉ vấn đề hiệu năng, và nên phán cùng việc chạm Commit Limit, Modified Page List, và I/O paging thực.6
6.2. Điều gì xảy ra khi bạn tiến gần Commit Limit
Khi System Commit Charge tới Commit Limit, các yêu cầu commit mới không chống được. Điều này dẫn tới cấp phát bộ nhớ tiến trình thất bại, ứng dụng sự cố, và hệ thống không đáp ứng.3
Ở đây, X/Y của Commit quan trọng hơn “RAM trống”. Dù bạn Trim Working Set để giải phóng RAM, việc chạm Commit Limit không được giải trừ khi chính Commit Charge giảm.
6.3. Ba vai trò của tệp trang
Tệp trang chủ yếu phục vụ các vai trò sau.
- Mở rộng Commit Limit
- Cho phép các trang đã sửa ít dùng được paging ra khỏi RAM
- Chống bản dump sự cố hệ thống, tùy cấu hình
Tắt tệp trang không phải trường hợp đơn giản “I/O đĩa luôn giảm và mọi thứ nhanh hơn”. Ngược lại, nó hạ Commit Limit, làm các trang đã sửa nhưng hiện không cần dễ ở lại RAM, và có thể khiến không thể bắt bản dump bạn cần khi sự cố xảy ra.36
Kích thước tệp trang phù hợp không quyết được chỉ từ RAM lắp đặt. Chính Microsoft giải thích rằng điều này không tổng quát hóa được, vì đỉnh System Commit Charge và loại dump sự cố cần khác nhau từng hệ thống.6
7. Phần tách RAM vật lý — đừng phán chỉ từ Available thấp
RAM vật lý không chỉ được dùng bởi Working Set của các tiến trình người dùng.
- Working Set mỗi tiến trình
- Bộ nhớ đệm tệp hệ thống
- Các danh sách trang như Standby, Modified, Free và Zeroed
- Paged Pool / Nonpaged Pool của kernel
- Bộ nhớ các trình điều khiển thiết bị giữ
- Kho nén bộ nhớ
- Các vùng dùng chung với hoặc đặt chỗ cho GPU và thiết bị khác
- Bộ nhớ phần cứng đặt chỗ
7.1. Available cũng gồm bộ nhớ đệm dùng lại được
Available MBytes của Windows không chỉ là RAM hoàn toàn không dùng. Đó là chỉ số, cùng Free và Zeroed, cũng gồm các trang Standby dùng lại được khi cần.12
- Free: trang hiện không được cấp cho mục đích nào
- Zeroed: trang đã được điền zero để giao an toàn cho tiến trình khác
- Standby: trang đã rời Working Set nhưng nội dung vẫn được đệm trong RAM
- Modified: trang nội dung đã đổi và cần được ghi lại vào phần chống đỡ thích hợp trước khi dùng lại
flowchart TB
accTitle: Di chuyển giữa Working Set và các danh sách trang
accDescr: Cho thấy trang không đổi đi Standby và trang đã sửa đi Modified, rồi truy cập lại, ghi lại, và dùng lại
workingSet["Working Set - đang dùng"]
workingSet -->|gỡ trang không đổi| standby["Standby - ứng viên dùng lại còn nội dung"]
workingSet -->|gỡ trang đã sửa| modified["Modified - chờ ghi lại"]
modified -->|ghi lại xong| standby
standby -->|truy cập lại| workingSet
standby -->|dùng lại cho mục đích khác| reused["Cấp cho mục đích khác"]
free["Free - chưa dùng"] -->|điền zero| zeroed["Zeroed - sẵn cho cấp phát mới"]
zeroed -->|truy cập sau khi cấp| workingSet
standby -.-> available["Gồm trong Available"]
free -.-> available
zeroed -.-> available
Hình 8: Available gồm không chỉ bộ nhớ hoàn toàn trống mà cả Standby, thứ dùng lại được khi cần.
“Vứt hết bộ nhớ đệm để tăng RAM trống” không luôn thắng. Nếu dữ liệu bạn cần vẫn ngồi trong Standby, truy cập lại có thể đưa nó về Working Set nhanh mà không đọc đĩa.
Vậy dù Free thấp trong Task Manager, nếu Available đủ và lỗi trang cứng hay chờ đĩa không gây vấn đề, Windows có thể chỉ đang dùng RAM hiệu quả như bộ nhớ đệm.
7.2. Khi RAM co lại mà không có tiến trình lớn
Không lạ khi tiêu thụ bộ nhớ không giải thích được dù cộng Private Working Set mọi tiến trình.
- Bộ nhớ đệm tệp và tệp ánh xạ bộ nhớ
- Nonpaged Pool / Paged Pool
- Trang trình điều khiển khóa
- Trang dùng chung
- Nén bộ nhớ
- Cấp phát liên quan ảo hóa hoặc GPU
Trong trường hợp này, thay vì tiếp tục nhìn danh sách tiến trình, hãy kiểm Use Counts, Processes, Priority Summary và File Summary trong RAMMap của Sysinternals. RAMMap là công cụ chính thức để tách bộ nhớ vật lý theo mục đích, danh sách trang và tệp.13
Nếu chỉ Nonpaged Pool tiếp tục lớn, đó là lúc nghi rò phía trình điều khiển hoặc kernel, chứ không phải Private Bytes của ứng dụng chế độ người dùng.
8. Lỗi trang — số cao một mình không bất thường
Page Fault xảy ra khi một tiến trình truy cập trang hiện không trong Working Set của nó. Dù tên có chữ “Fault”, đây không phải thất bại ngoại lệ — đó là cơ chế bình thường vận hành bộ nhớ ảo.1
8.1. Lỗi trang mềm
Chúng được giải mà không đọc từ đĩa.
- Trang vẫn ở Standby hoặc Transition
- Cùng trang dùng chung đã ở Working Set tiến trình khác
- Trang đã commit được truy cập lần đầu và được gán trang zero
- Đọc trước của trình quản lý bộ nhớ đã đưa nó vào RAM
Vì thế, \Memory\Page Faults/sec lớn không nhất thiết nghĩa I/O đĩa hay độ trễ đang xảy ra.
8.2. Lỗi trang cứng
Chúng cần đọc nội dung từ Backing Store trên đĩa. Nguồn không giới hạn ở tệp trang.
- Mã và dữ liệu trong
.exehoặc.dll - Tệp ánh xạ bộ nhớ
- Tệp trang
flowchart TB
accTitle: Nhánh giữa lỗi trang mềm và cứng
accDescr: Khi truy cập trang không trong Working Set, xử lý như lỗi trang mềm nếu không cần I/O lưu trữ, hoặc lỗi trang cứng nếu cần
access["Truy cập trang không trong Working Set"] --> storageIo{"Có cần I/O lưu trữ không"}
storageIo -->|Không - Standby, dùng chung, demand-zero, v.v.| soft["Lỗi trang mềm"]
soft --> resident["Vào Working Set mà không đọc đĩa"]
storageIo -->|Có| hard["Lỗi trang cứng"]
hard --> source{"Đọc từ đâu"}
source --> image["EXE / DLL"]
source --> mapped["Tệp ánh xạ bộ nhớ"]
source --> pagefile["Tệp trang"]
image --> loaded["Vào Working Set sau khi tải"]
mapped --> loaded
pagefile --> loaded
Hình 9: Chỉ tên “Page Fault” không cho biết I/O đĩa có xảy ra.
Microsoft liệt kê \Memory\Pages/sec, \Memory\Page Reads/sec và \Memory\Pages Input/sec trong các bộ đếm đo lỗi cứng. Vì chúng cao không nhất thiết nghĩa bộ nhớ thấp, hãy tương quan với Available MBytes, độ trễ đĩa và thời gian đáp thực.6
8.3. Đừng đặt một ngưỡng chăn cho tất cả
Một giá trị cố định như “bất cứ gì trên 1000 Page Faults/sec là bất thường” đổi nghĩa tùy lưu trữ, kích thước trang, tải công việc và tính cục bộ truy cập.
Trong thực tiễn, xếp các thứ sau trên cùng một trục thời gian.
Memory\Available MBytesMemory\Pages Input/secMemory\Page Reads/sec- Độ trễ đọc / hàng đợi trên đĩa đích
- Working Set và Private Bytes của tiến trình đích
- Thời gian xử lý ứng dụng, hết hạn, và đáp ứng UI
Nếu Available giảm cùng lúc tải tăng, Pages Input/sec và chờ đĩa tăng, và thời gian xử lý cũng xấu đi, điều đó cho bạn căn cứ nghi paging do áp lực bộ nhớ vật lý.
9. Màn hình hay công cụ nào để kiểm điều gì
| Điều bạn muốn biết | Chỉ số kiểm trước | Công cụ chính |
|---|---|---|
| Lượng tiến trình đích hiện có trong RAM | Working Set | Task Manager, Process Explorer, Get-Process |
| Phần riêng của đó — RAM riêng tiến trình | Private Working Set / Working Set - Private | Cột Details của Task Manager, Process Explorer, PerfMon |
| Lượng commit riêng tiến trình đích | Private Bytes / Commit Size | Process Explorer, PerfMon, VMMap, Get-Process |
| Dải địa chỉ ảo của tiến trình | Virtual Bytes / Size | Process Explorer, VMMap, Get-Process |
| Dư commit tổng thể hệ thống | Committed Bytes / Commit Limit | Task Manager [Performance], PerfMon |
| Dư dùng lại của RAM vật lý | Available MBytes | Task Manager, PerfMon |
| Phần tách Standby, Modified và bộ nhớ đệm tệp | Danh sách trang / tách theo mục đích | RAMMap |
| Điều gì lớn trong Private Bytes | Heap / Private Data / Managed Heap, v.v. | VMMap, WinDbg, dump riêng runtime |
| Paging có đĩa | Pages Input/sec, Page Reads/sec, độ trễ đĩa | PerfMon, WPR/WPA |
flowchart TB
accTitle: Chọn công cụ điều tra bộ nhớ Windows
accDescr: Công cụ dùng tùy đích là một tiến trình hay cả hệ thống, một thời điểm hay chuỗi thời gian, và bạn có cần lần sự giữ bên trong runtime
question["Bạn muốn cô lập điều gì"]
question --> processScope{"Đích có phải một tiến trình"}
processScope -->|có| processTime{"Một thời điểm hay chuỗi thời gian"}
processTime -->|phần tách một thời điểm| vmmap["VMMap"]
processTime -->|chuỗi thời gian| perfmon["PerfMon / PowerShell"]
processScope -->|cả hệ thống| systemView{"Phần tách RAM vật lý hay trục thời gian"}
systemView -->|phần tách RAM vật lý| rammap["RAMMap"]
systemView -->|trục thời gian gồm CPU, I/O và chờ| wpa["WPR / WPA"]
question --> runtime{"Cần lần sự giữ bên trong runtime"}
runtime -->|heap .NET| dotnet["dotnet-dump / PerfView"]
runtime -->|heap gốc| native["WinDbg / Application Verifier"]
Hình 10: Quyết phạm vi và trục thời gian trước cho phép bạn chọn đúng công cụ cần, không hơn không kém.
9.1. Task Manager
Trong Task Manager, hãy nhìn các màn hình tách nhau.
- [Processes] hoặc [Details]: họ Working Set và họ Commit Size của từng tiến trình
- [Performance] → [Memory]: In use, Available, Committed, Cached, Paged pool, Non-paged pool toàn hệ thống
Đừng phán từ cột tên “Memory” một mình — nhấp phải tiêu đề cột trên tab [Details] và thêm các cột bạn cần, như Working Set, Peak Working Set và Commit Size. Tên cột hơi khác theo phiên bản Windows và ngôn ngữ hiển thị, nên xác nhận cột thực sự nghĩa gì trước khi ghi.
9.2. Bắt chuỗi thời gian bằng PowerShell
Nếu biết ID tiến trình đích, bạn có thể bắt xu hướng Working Set, Private Bytes và Virtual Bytes cùng lúc bằng Get-Process.
param(
[Parameter(Mandatory)]
[int]$ProcessId,
[int]$IntervalSeconds = 5,
[int]$SampleCount = 60
)
$samples = for ($i = 0; $i -lt $SampleCount; $i++) {
$process = Get-Process -Id $ProcessId -ErrorAction Stop
[pscustomobject]@{
Timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
ProcessId = $process.Id
WorkingSetMB = [math]::Round($process.WorkingSet64 / 1MB, 1)
PrivateBytesMB = [math]::Round($process.PrivateMemorySize64 / 1MB, 1)
VirtualBytesMB = [math]::Round($process.VirtualMemorySize64 / 1MB, 1)
Handles = $process.HandleCount
Threads = $process.Threads.Count
}
Start-Sleep -Seconds $IntervalSeconds
}
$samples | Format-Table -AutoSize
$samples | Export-Csv .\memory-samples.csv -NoTypeInformation -Encoding utf8
Process.WorkingSet64 của .NET tương ứng Working Set, PrivateMemorySize64 tương ứng Private Bytes, và VirtualMemorySize64 tương ứng Virtual Bytes.141516
Với ứng dụng nhiều phiên bản, hãy theo PID chứ không theo tên. Với giám sát dài hạn mà khởi động lại đổi PID, hãy thiết kế thu thập để ghi thời điểm bắt đầu, tên dịch vụ và tương tự, để đích không bao giờ bị nhầm.
9.3. Đặt hệ thống và một tiến trình trên cùng trục thời gian bằng PerfMon
Ghi ít nhất các thứ sau cùng nhau làm cô lập dễ hơn nhiều.
\Process(<đích>)\ID Process
\Process(<đích>)\Working Set
\Process(<đích>)\Working Set - Private
\Process(<đích>)\Private Bytes
\Process(<đích>)\Virtual Bytes
\Memory\Available MBytes
\Memory\Committed Bytes
\Memory\Commit Limit
\Memory\Pages Input/sec
\Memory\Page Reads/sec
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Bytes
Khi nhiều tiến trình chia cùng tên, hoặc khởi động lại xảy ra lúc giám sát, chỉ tên phiên bản — Process(name) hoặc Process(name#N) — không ghim được đích. Ghi cả ID Process cho mỗi mẫu, và chỉ nhận phiên bản có giá trị khớp PID bạn đang theo. Khi bạn bắc qua lần khởi động lại đổi PID, hãy ghi riêng thời điểm chuyển nữa.
Tên bộ đếm hiệu năng Windows có thể được địa phương hóa tùy ngôn ngữ hiển thị. Nếu chỉ định tên tiếng Anh trực tiếp trong PowerShell không tìm thấy, hãy thêm bộ đếm qua GUI PerfMon, hoặc kiểm tên trong môi trường địa phương bằng Get-Counter -ListSet *.
9.4. Đừng lẫn vai trò VMMap và RAMMap
- VMMap: tách bộ nhớ ảo và Working Set của một tiến trình thành Heap, Image, Mapped File, Private Data, Managed Heap và tương tự
- RAMMap: tách RAM vật lý cả hệ thống theo mục đích, danh sách trang, tiến trình và tệp
“Điều gì làm Private Bytes tiến trình này lớn” là việc của VMMap; “RAM mà danh sách tiến trình không giải thích được dùng cho gì” là việc của RAMMap.1713
10. Đọc triệu chứng từ tổ hợp số
| Mẫu quan sát | Giả thuyết đầu | Việc kiểm tiếp |
|---|---|---|
| Working Set tăng, Private Bytes ổn | Lần truy cập đầu tới trang sẵn có, DLL dùng chung, tệp ánh xạ, bộ nhớ đệm tệp | Image / Mapped File của VMMap, Pages Input/sec |
| Private Bytes tăng, Working Set ổn | Commit riêng lớn nhưng không trú hoặc đã bị Trim | Heap / Private Data / Managed Heap của VMMap |
| Cả hai tăng ngay sau khởi động, rồi nằm ngang | JIT, bộ nhớ đệm, pool, làm nóng khởi tạo | Nó có lớn lại dưới cùng tải thêm không |
| Sàn Private Bytes tăng mỗi vòng tải | Rò rỉ, bộ nhớ đệm không trần, hoặc bộ cấp phát giữ sau khi nhả | Ảnh chụp VMMap trước sau, dump heap |
| Chỉ Working Set đột ngột giảm rồi trở lại khi hoạt động | OS hoặc ứng dụng Trim Working Set | Private Bytes, Pages Input/sec, thời gian đáp |
| X trong Committed X/Y tiến gần Y | Áp lực commit toàn hệ thống | Người tiêu Private Bytes hàng đầu, Paged/Nonpaged Pool, thiết lập tệp trang |
| Available thấp, Pages Input/sec và độ trễ đĩa cao | Áp lực RAM vật lý và paging cứng | Người tiêu Working Set hàng đầu, RAMMap, tương quan tải |
| Mức dùng RAM cao nhưng không có tiến trình lớn | Bộ nhớ đệm, trang dùng chung, pool kernel, trình điều khiển, nén, v.v. | RAMMap, Pool Nonpaged/Paged Bytes |
| Còn RAM trống, thế mà chỉ ứng dụng 32-bit thất bại | Trần không gian địa chỉ ảo hoặc phân mảnh | Free/Reserved của VMMap, thiết lập LAA của tệp thực thi |
| Private Bytes cao nhưng không lớn khi lặp xử lý | Pool hoặc bộ nhớ đệm có thể giữ mực nước cao | Giới hạn của nó, hành vi dùng lại, ổn định sau đỉnh |
Điều quan trọng nhất của bảng này là đọc theo tổ hợp, không từ một giá trị một mình.
11. Quy trình thực tiễn điều tra rò rỉ bộ nhớ
11.1. Trước hết quyết điều kiện tái hiện và điểm ổn định
“Nó lớn trong vài ngày” một mình không so sánh được.
- Làm nóng sau khởi động gồm bao nhiêu
- Một chu kỳ thao tác gồm gì
- Chờ bao nhiêu giây sau một chu kỳ
- Bao nhiêu vòng mới tới trần bộ nhớ đệm
- Có dùng cùng đầu vào cho bản dựng khỏe và bản có vấn đề không
Hãy quyết tất cả.
11.2. Ghi tiến trình và hệ thống đồng thời
Ít nhất, giữ các thứ sau được ghi cùng dấu thời gian.
- Working Set của đích
- Private Bytes của đích
- Virtual Bytes của đích
- Committed Bytes / Commit Limit của hệ thống
- Available MBytes
- Pages Input/sec
- Số handle, số luồng
- Số thao tác hoặc mục đã xử lý
Nếu Private Bytes của tiến trình ổn trong khi Commit hệ thống tiếp tục lớn, bạn cần mở phạm vi sang tiến trình khác, kernel, trình điều khiển và phần dùng chung.
11.3. Quyết “chiều” nào đang lớn trước
- Chỉ Working Set: trang trú, dùng chung hoặc từ tệp, Trim và tải lại
- Private Bytes: commit riêng tiến trình
- Chỉ Virtual Bytes: Reserve, ánh xạ, phân mảnh không gian địa chỉ
- Chỉ System Commit: gồm tiến trình khác và phía kernel
- Nonpaged Pool: phía trình điều khiển/kernel
- Handles / GDI / USER: rò tài nguyên ngoài bộ nhớ
Bỏ thứ tự này rồi nhảy thẳng tới lấy dump, bạn sẽ đọc một núi thông tin trong khi nhắm sai thứ.
11.4. Tiến tới phần tách
- Tiến trình gốc: VMMap, WinDbg, Application Verifier, theo dấu heap
- .NET:
dotnet-counters,dotnet-gcdump,dotnet-dump, PerfView - Toàn hệ thống: RAMMap, PerfMon, WPR/WPA
- Pool kernel: PoolMon, WinDbg
VMMap hiện bộ nhớ ảo đã commit của một tiến trình, và Working Set cấp cho từng phần, tách theo loại. Bạn thu hẹp mức tăng Private Bytes xuống Heap, Private Data, Managed Heap hay Mapped File được bao xa tạo khác biệt lớn tới chi phí điều tra tiếp.17
11.5. Sau sửa, so xu hướng dưới cùng điều kiện
Không đủ đỉnh khác trước và sau sửa. Nếu giá trị khởi khác, so sánh dễ đảo.
- Cùng trạng thái khởi động
- Cùng đầu vào
- Cùng số thao tác
- Cùng thời gian chờ
- Cùng khoảng lấy mẫu
— và so giá trị sàn cùng xu hướng sau mỗi chu kỳ. Chứng sửa rò rỉ không phải “cực đại nhỏ hơn”, mà là mức tăng nay hội tụ ngay khi cùng tải được lặp.
12. Diễn lại các hiểu lầm thường gặp
Hiểu lầm 1: Memory của Task Manager bằng tổng lượng ứng dụng đã cấp phát
Diễn lại: Kiểm cột nào. Với họ Working Set đó là lượng hiện trú trong RAM; với họ Commit Size đó là commit riêng của tiến trình đó.
Hiểu lầm 2: Private Bytes bằng số byte trên tệp trang
Diễn lại: Private Bytes là Commit Charge riêng. Đó là lượng được hứa logic gồm cả trang hiện trong RAM và trang sẽ được chống bằng tệp trang nếu và khi cần.
Hiểu lầm 3: Commit X/Y bằng mức dùng tệp trang / dung lượng tệp trang
Diễn lại: X là Commit Charge toàn hệ thống, và Y là Commit Limit. Tệp trang mở rộng Y, nhưng X không dịch trực tiếp thành mức dùng trên đĩa.
Hiểu lầm 4: Page Faults/sec cao nghĩa đang hoán trang ra đĩa
Diễn lại: Điều này gồm cả lỗi mềm. Kiểm Pages Input/sec, Page Reads/sec và độ trễ đĩa để xem I/O đĩa có thực sự tham gia.
Hiểu lầm 5: Free RAM thấp nghĩa thiếu bộ nhớ
Diễn lại: Nhìn Available, Standby, paging cứng và thời gian đáp. Lấp RAM bằng bộ nhớ đệm dùng lại được là bình thường.
Hiểu lầm 6: Thu Working Set nghĩa đã sửa rò rỉ bộ nhớ
Diễn lại: Bạn có thể chỉ đuổi trang khỏi RAM. Kiểm Private Bytes và những gì được giữ trong heap thực sự có giảm.
Hiểu lầm 7: Private Bytes tăng xác nhận rò rỉ
Diễn lại: Bạn chỉ phán được sau khi kiểm nó có hội tụ khi cùng tải được lặp, loại bộ nhớ nào lớn, và đó có phải bộ nhớ đệm giải phóng được.
13. Tóm tắt
- “Mức dùng bộ nhớ” của Windows không phải một con số. Hãy nghĩ không gian địa chỉ, commit, trú RAM và khả năng dùng chung tách nhau.
- Working Set là các trang hiện trong RAM, gồm cả Private và Shared. Private Working Set là các trang trú riêng tiến trình trong đó.
- Private Bytes là Commit Charge riêng tiến trình; nó không phải lượng hiện trong RAM cũng không phải lượng thực sự ghi vào tệp trang.
- Committed X/Y là Commit Charge / Commit Limit toàn hệ thống. Tệp trang chủ yếu chống Commit Limit, đuổi trang đã sửa, và bản dump sự cố.
- Địa chỉ ảo đã Reserved, trang đã Committed, và trang thực sự được chạm rồi vào Working Set là các giai đoạn tách.
- Page Fault là thao tác bình thường, và lỗi mềm không đọc từ đĩa. Lỗi cứng cũng có thể xảy ra không chỉ từ tệp trang mà từ EXE, DLL hoặc tệp ánh xạ.
- Rò rỉ bộ nhớ được chứng không bởi kích thước tại một thời điểm, mà bởi giá trị sàn và xu hướng sau cùng tải, cùng phần tách.
- Đường cơ bản: VMMap cho phần tách từng tiến trình, RAMMap cho RAM vật lý toàn hệ thống, PerfMon cho chuỗi thời gian, và công cụ dump chuyên cho những gì bên trong runtime.
Lần tới bạn nhận ra trong Task Manager rằng “bộ nhớ đang lớn”, hãy bắt đầu bằng cách tự hỏi điều này.
Điều đang lớn là Working Set, Private Bytes, Virtual Bytes, hay System Commit?
Chỉ câu hỏi đó làm điểm vào điều tra của bạn chính xác hơn nhiều.
Bài viết liên quan
- Phân biệt độ trễ GC với rò rỉ bộ nhớ trong .NET — quy trình thực tiễn quan sát, so sánh và chứng minh bộ nhớ tăng
- Process Explorer / Handle / VMMap trong thực tiễn — truy đuổi treo, rò rỉ và “tệp đang được dùng” từ trạng thái ngay lúc này
- Những cái bẫy của bộ nhớ dùng chung và thực hành tốt nhất
- Độ sâu I/O Windows (Phần 4) — Cache Manager: WriteFile của bạn thực sự tới đĩa khi nào?
- Điều tra sự cố chạy dài của ứng dụng camera công nghiệp - rò rỉ handle (Phần 1)
Lĩnh vực tư vấn liên quan
KomuraSoft LLC đảm nhận điều tra nguyên nhân gốc rễ kết hợp PerfMon, VMMap, RAMMap, WinDbg và công cụ chẩn đoán .NET cho bộ nhớ ứng dụng Windows tăng, hiệu năng giảm sau chạy dài, OutOfMemory ở tiến trình 32-bit, và thiếu bộ nhớ chỉ xảy ra trong môi trường khách. Chúng tôi không dừng ở chỉ “bộ nhớ cao” — chúng tôi cô lập vùng nào lớn, qua thao tác nào, vì sao, và được tham chiếu hay giữ từ đâu.
- Phát triển ứng dụng Windows
- Điều tra lỗi và nguyên nhân
- Tư vấn kỹ thuật và đánh giá thiết kế
- Liên hệ với chúng tôi
Liên kết tham khảo
-
Microsoft Learn, Working Set. Về Working Set của một tiến trình là tập trang hiện trú trong bộ nhớ vật lý, gồm trang dùng chung; khác biệt giữa lỗi trang mềm và cứng; trang Transition; và việc gỡ trang khỏi Working Set. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, PROCESS_MEMORY_COUNTERS_EX2 structure. Về định nghĩa WorkingSetSize, PrivateWorkingSetSize, PrivateUsage và SharedCommitUsage, và về cả PagefileUsage lẫn PrivateUsage đều biểu diễn Commit Charge của tiến trình. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Introduction to page files. Về tệp trang chống đuổi trang đã sửa, dump sự cố hệ thống, và mở rộng System Commit Limit; định nghĩa System Commit Charge và Commit Limit; và cách đo qua Task Manager cùng bộ đếm hiệu năng. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Page State. Về các trạng thái Free, Reserved và Committed của một trang ảo, và về trang Reserved không có lưu trữ vật lý gắn và không truy cập được. ↩ ↩2
-
Microsoft Learn, VirtualAlloc function. Về khác biệt MEM_RESERVE và MEM_COMMIT; việc commit bị tính vào bộ nhớ tổng thể hệ thống và tệp trang; và trang vật lý thực đôi khi chưa được cấp đến lần truy cập đầu. ↩ ↩2 ↩3
-
Microsoft Learn, How to determine the appropriate page file size for 64-bit versions of Windows. Về kích thước tệp trang tùy đỉnh Commit Charge và yêu cầu dump sự cố; lỗi trang cứng đọc không chỉ từ tệp trang mà cả EXE, DLL và tệp ánh xạ bộ nhớ; cùng các bộ đếm hiệu năng liên quan. ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
Microsoft Learn, Virtual Address Space. Về mỗi tiến trình có không gian địa chỉ ảo và bảng trang độc lập riêng, và địa chỉ ảo không phải địa chỉ vật lý tự thân. ↩
-
Microsoft Learn, Memory Limits for Windows and Windows Server Releases. Về không gian địa chỉ ảo chế độ người dùng của tiến trình 32-bit thường là 2GB, và trở thành 2GB hoặc 4GB trên Windows 64-bit tùy IMAGE_FILE_LARGE_ADDRESS_AWARE. ↩
-
Microsoft Learn, SetProcessWorkingSetSize function. Về giá trị tối thiểu và tối đa Working Set không bảo đảm trú; khả năng làm trống Working Set; và thiết lập hay thao tác quá mức có thể làm hiệu năng hệ thống xấu đi. ↩
-
Microsoft Learn, Memory Performance Information. Về tương ứng giữa bộ đếm hiệu năng Windows, API quản lý bộ nhớ, và hiện thị Task Manager, gồm Working Set / Working Set - Private / Private Bytes của đối tượng Process, và Committed Bytes / Commit Limit của đối tượng System. ↩
-
Microsoft Learn, MapViewOfFile function. Về
FILE_MAP_COPYkhiến mọi trang có thể copy-on-write, nên Commit Charge cho cả view được đặt chỗ để chống bằng tệp trang lúc ánh xạ. ↩ -
Microsoft Learn, Understanding Node Metrics and Properties in HPC Cluster Manager. Về Available Physical Memory được tính là tổng các danh sách Zeroed, Free và Standby, và về nghĩa mỗi danh sách trang đó. ↩
-
Microsoft Sysinternals, RAMMap. Về phân tích mức dùng bộ nhớ vật lý Windows theo mục đích, danh sách trang, tiến trình, ưu tiên, trang vật lý và tệp. ↩ ↩2
-
Microsoft Learn, Process.WorkingSet64 Property. Về
WorkingSet64trả Working Set của tiến trình theo byte, tương ứng bộ đếm hiệu năng Working Set của đối tượng Process. ↩ -
Microsoft Learn, Process.PrivateMemorySize64 Property. Về
PrivateMemorySize64trả bộ nhớ riêng tiến trình không dùng chung với tiến trình khác được, tương ứng bộ đếm hiệu năng Private Bytes. ↩ -
Microsoft Learn, Process.VirtualMemorySize64 Property. Về
VirtualMemorySize64trả lượng bộ nhớ ảo cấp cho tiến trình, tương ứng bộ đếm hiệu năng Virtual Bytes. ↩ -
Microsoft Sysinternals, VMMap. Về tách bộ nhớ ảo đã commit của một tiến trình theo loại, và hiện bộ nhớ vật lý (Working Set) cấp cho mỗi phần, cùng bản đồ bộ nhớ chi tiết. ↩ ↩2
Bài viết liên quan
Các bài viết gần đây có cùng thẻ để tìm hiểu sâu hơn những chủ đề lân cận.
Chiều sâu bộ nhớ Windows (phần 2) — Đời sống của một trang vật lý: năm danh sách và sự thật về tệp trang
Bài viết nối cơ sở PFN, Standby, Modified, nén bộ nhớ và tệp trang để giải thích trang vật lý đi đâu sau khi rời Working Set.
Chiều sâu bộ nhớ Windows (phần 1) — Khoảnh khắc địa chỉ ảo trở thành RAM vật lý: page fault từ đầu đến cuối
Bài viết nối VirtualAlloc, VAD, bảng trang, TLB, demand-zero và hard fault để giải thích khoảnh khắc một địa chỉ ảo được gán RAM vật lý.
Đọc mã lỗi Windows — cấu trúc ba lớp Win32, HRESULT và NTSTATUS
Khi 0x80004005 xuất hiện, hãy tách nó trước khi tìm. Bài viết trình bày ba lớp Win32, HRESULT và NTSTATUS, mẫu 0x8007xxxx, và cách tra vớ...
API thread pool Win32 — Đồng thời mà không tạo luồng, với CreateThreadpoolWork
Bạn đang rải các lời gọi CreateThread khắp mã native? Bài viết này giải thích API thread pool Win32 được thiết kế lại từ Vista — bốn đối ...
Named pipe trong thực tiễn — IPC chuẩn của Windows, từ thiết kế đến bảo mật
Hướng dẫn thực tiễn về named pipe, cơ chế giao tiếp giữa các tiến trình chuẩn của Windows. Bài viết sắp xếp, từ nguồn gốc, việc chọn giữa...
Chủ đề liên quan
Các trang này đặt chủ đề trong bối cảnh rộng hơn của dịch vụ và quyết định.
Chủ đề kỹ thuật Windows
Cổng vào phát triển Windows, điều tra lỗi và khai thác tài sản hiện có.
Dịch vụ liên quan đến chủ đề này
Bài viết liên quan trực tiếp đến các dịch vụ sau.
Phát triển ứng dụng Windows
Ứng dụng nghiệp vụ, tích hợp thiết bị và công cụ liên lạc, từ yêu cầu đến phát triển.
Câu hỏi thường gặp
Các câu hỏi thường gặp khi tư vấn về chủ đề của bài viết.
- Cột "Memory" của Task Manager có phải tổng bộ nhớ ứng dụng đã cấp phát không?
- Không. Task Manager có nhiều cột bộ nhớ — họ Working Set, họ Private Working Set, Commit Size và khác — và nghĩa tùy màn hình cùng cột bạn đang xem. Working Set là các trang hiện trú trong RAM; Private Bytes hoặc Commit Size là lượng commit riêng của tiến trình đó. Đừng đọc một cột "Memory" duy nhất như tổng dung lượng ứng dụng đã cấp phát, hay như kích thước một chỗ rò.
- Working Set khác Private Bytes thế nào?
- Working Set là lượng trang tiến trình đó nhìn thấy và hiện trú trong RAM vật lý, gồm cả trang dùng chung được như mã DLL và tệp ánh xạ bộ nhớ. Private Bytes là lượng bộ nhớ đã commit dùng riêng cho tiến trình đó, bất kể hiện có trú trong RAM hay không. Hai giá trị vì thế không bao giờ bằng nhau, và không bên nào luôn lớn hơn bên kia.
- "Committed 18/32GB" trên Task Manager có nghĩa 18GB đã được ghi vào tệp trang không?
- Không. Con số trái là tổng commit mà cả hệ thống hiện đang hứa sẽ chống đỡ; con số phải là trần commit hệ thống có thể chống. Trần được quyết đại thể bởi RAM cộng tệp trang, nhưng không phải toàn bộ tổng trái thực sự nằm trên tệp trang. Phần lớn trang đã commit ở trong RAM, và một số trang đã commit chưa từng được gán trang vật lý. Trong khi đó, các trang có thể tải lại từ tệp gốc — như EXE, DLL và tệp ánh xạ bộ nhớ — không nhất thiết tăng Private Commit bằng đúng mức chúng tăng Working Set.
- Có thể gặp OutOfMemory dù vẫn còn RAM trống không?
- Có. Cấp phát có thể thất bại vì lý do khác RAM vật lý, gồm tiến trình 32-bit hết không gian địa chỉ ảo, thiếu dải địa chỉ trống liên tục đủ lớn, trần commit hệ thống, hoặc giới hạn riêng của Job Object hay runtime. Đặc biệt, tiến trình 32-bit trên Windows 64-bit thường bị giới hạn 2GB không gian địa chỉ ảo chế độ người dùng trừ khi nó Large Address Aware.
- Tắt tệp trang có làm Windows nhanh hơn không?
- Bạn không thể giả định như một quy tắc chung. Tắt tệp trang hạ trần commit của hệ thống, làm khó đuổi các trang đã sửa nhưng không dùng ra khỏi RAM, và ảnh hưởng cách có thể cấu hình bản dump sự cố. Kích thước tệp trang nên được quyết bằng cách đo đỉnh commit charge và bản dump sự cố bạn cần — không phải thiết lập để tắt mà không có lý do.
- Page Faults/sec cao có nghĩa hệ thống thiếu bộ nhớ không?
- Chỉ thế không đủ để kết luận. Lỗi trang gồm lỗi mềm, có thể giải từ trang Standby trong RAM hoặc trang dùng chung với tiến trình khác, và lỗi cứng, đọc từ đĩa. Thay vì nhìn Page Faults/sec riêng, hãy kiểm Pages Input/sec, Page Reads/sec, Available MBytes, độ trễ đĩa và thời gian xử lý cùng nhau trên cùng một trục thời gian.