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

· · Windows, Quản lý bộ nhớ, VirtualAlloc, Page fault, VAD, Giám sát hiệu năng

Truyền MEM_COMMIT cho VirtualAlloc làm Commit tăng ngay lúc đó. Working Set, tuy nhiên, không nhất thiết tăng cùng lượng. Vậy bộ nhớ bạn nghĩ đã cấp nằm ở đâu?

Câu trả lời là hầu hết trang chưa có RAM vật lý tương ứng. Windows trì hoãn gán trang vật lý cho đến khi ứng dụng thực sự chạm trang. Khi lần truy cập đầu khiến CPU nâng page fault, trình quản lý bộ nhớ xem VAD, PTE, thuộc tính bảo vệ và backing store, rồi gắn RAM từng trang nếu cần.1

Bài này lần theo đường «byte đầu tiên bạn chạm» đi đến RAM vật lý. Nếu muốn sắp xếp trước ý nghĩa các con số như Working Set và Commit, xem bài dẫn nhập «What Does Windows’ “Memory Usage” Actually Mean? — Correctly Reading Working Set, Private Bytes, Commit, and the Page File». Series này không định nghĩa lại thuật ngữ dùng ở đó; nó đào từ phía cơ chế «vì sao con số ra như vậy».

«Chiều sâu bộ nhớ Windows» — cả 3 phần

  1. Phần 1 (bài này): địa chỉ ảo và page fault
    Ta lần theo khi nào vùng cấp bằng VirtualAlloc nhận RAM vật lý.
  2. Phần 2: đời một trang vật lý
    Ta lần theo trang rời Working Set di chuyển qua Modified, Standby, Free và Zeroed như thế nào.
  3. Phần 3: đối tượng section và copy-on-write
    Ta lần theo vì sao DLL, ánh xạ tệp và bộ nhớ dùng chung có thể chia sẻ trang vật lý.

Câu hỏi phần 1 trả lời chỉ có một.

Vào khoảnh khắc nào địa chỉ ảo đã Commit trở thành RAM vật lý?

Độc giả dự kiến là nhà phát triển và vận hành muốn hiểu từ cơ chế mức dùng bộ nhớ ứng dụng Windows, page fault ngay sau khởi động, 0xC0000005, và các số trong VMMap cùng PerfMon. Điều kiện tiên quyết là Windows 10/11 hoặc Windows Server hiện hành, và nền cần có là con trỏ cùng cơ bản VirtualAlloc; không cần kinh nghiệm bố trí bit bảng trang hay trình gỡ lỗi nhân. Độ khó trung cấp. Ta dùng tên cấu trúc nội bộ, nhưng không giả định bố trí không tài liệu phụ thuộc bản dựng Windows cụ thể.

1. Kết luận trước

Luồng bộ nhớ riêng thông thường, một dòng, là thế này.

Reserve dành sẵn dải địa chỉ ảo, Commit ghi nhận commit charge vào giới hạn commit để bảo đảm chỗ giữ nội dung trong tương lai, và page fault ở lần truy cập đầu gán trang vật lý.

Nói cách khác, MEM_COMMIT không phải lệnh «cấp RAM ngay». Tài liệu Microsoft về VirtualAlloc cũng bảo đảm nội dung ban đầu của trang đã Commit là không, đồng thời giải thích trang vật lý thực không được gán cho đến khi địa chỉ ảo được truy cập.1

Dẫu vậy, cũng không chính xác khi khẳng định «Reserve/Commit chỉ ghi vào VAD». Thực tế, Reserve chủ yếu tạo VAD biểu diễn dải địa chỉ ảo và thuộc tính của nó, còn Commit tăng Commit Total hệ thống và ghi trạng thái đã commit của dải. Các tầng bảng trang trung gian và từng PTE được xây lười khi cần, và gắn kết cuối với RAM vật lý thường xảy ra ở lần truy cập đầu.

Commit không phải lời hứa rỗng; đó là lời hứa toàn hệ thống rằng nội dung có thể được giữ trong tương lai ở RAM hoặc backing store thích hợp. Điểm vào hiện thực hóa lời hứa đó từng trang một chính là page fault.

Điều xảy ra ở Reserve, Commit và lần truy cập đầuMEM_RESERVE ghi dải và thuộc tính vào VAD, MEM_COMMIT tiêu hao Commit Total để hứa lưu trữ, và page fault ở lần truy cập đầu gán trang vật lý rồi thêm vào Working Set1. MEM_RESERVE2. MEM_COMMIT3. Lần truy cập đầu(Touch)Ghi dải và thuộc tính vào VADTiêu hao Commit Total(chưa có trang vật lý)Page faultGắn trang vật lý đã xóa không vào PTEThêm vào Working Set và thực thi lại lệnh

Hình 1: Reserve, Commit và Touch là các sự kiện riêng. RAM vật lý chỉ được gắn ở bước cuối, lần truy cập đầu.

2. Ba sổ cái theo dõi một trang ảo

Để hiểu đường từ địa chỉ ảo tới RAM vật lý, cần phân biệt ba loại sổ cái Windows giữ.

Sổ cái Đơn vị Vai trò
VAD Dải địa chỉ ảo Quản lý vùng là gì, Reserve/Commit, bảo vệ và tương ứng section
Bảng trang / PTE Trang ảo Biểu diễn bản dịch hiện tại sang trang vật lý, hoặc trạng thái chưa hiện thực
Cơ sở PFN Trang vật lý Theo dõi sở hữu, tham chiếu và trạng thái từng trang RAM

VAD giữ thông tin về dải, PTE về trang ảo, cơ sở PFN về trang vật lý. Bộ xử lý page fault đối chiếu chúng để quyết định truy cập có thể tiếp tục không.

Ba sổ cái từ địa chỉ ảo tới RAM vật lýĐịa chỉ ảo do VAD quản lý ở độ hạt dải và PTE ở độ hạt trang ảo, còn cơ sở PFN theo dõi trang vật lý là đích bản dịch của PTE ở độ hạt trang vật lýĐánh giá Reserve/Commit và bảo vệBản dịch hợp lệĐịa chỉ ảoVAD(sổ cái dải)PTE(sổ cái trang ảo)Cơ sở PFN(sổ cái trang vật lý)Trang RAM vật lý

Hình 2: Ba sổ cái ở các độ hạt khác nhau. Xử lý fault đối chiếu VAD và PTE rồi phản ánh kết quả sang phía PFN.

Nhân vật chính của bài này là VAD và PTE. Ta sẽ xem cơ sở PFN từ phía trang vật lý ở phần 2.

3. Reserve, Commit và Touch là các sự kiện riêng

3.1. Reserve — chiếm một địa chỉ

Trước hết, dành một dải địa chỉ ảo liên tục 256MiB.

void* base = VirtualAlloc(
    nullptr,
    256ull * 1024 * 1024,
    MEM_RESERVE,
    PAGE_NOACCESS);

Điều xảy ra tại điểm này chỉ là một địa chỉ được dành sẵn trong không gian ảo của tiến trình để các cấp phát khác không dùng dải này. MEM_RESERVE không gán lưu trữ vật lý trong RAM hay tệp trang.1

Vì tiến trình 64-bit có không gian ảo rất lớn, việc Reserve dải lớn trước rồi Commit chỉ các phần cần sau trở nên thực tế.

3.2. Commit — hứa rằng có thể giữ được

Tiếp theo, Commit dải đã dành.

void* committed = VirtualAlloc(
    base,
    256ull * 1024 * 1024,
    MEM_COMMIT,
    PAGE_READWRITE);

Khi thành công, lượng được hứa phản ánh trong Commit Total hệ thống — và thường trong Private Bytes của tiến trình — tăng. Dù vậy, 256MiB trang vật lý không xếp hàng cùng lúc. Các trang thông thường vẫn chưa được gán vật lý cho đến lần truy cập đầu.12

Vậy Commit để làm gì? Là khi hệ thống không nhận nổi lời hứa, nó có thể trả thất bại ngay lúc Commit, chứ không giữa lúc dùng bộ nhớ.

3.3. Touch — khi trang vật lý trở nên cần

Cuối cùng, phép gán sau ghi lần đầu vào trang đầu.

static_cast<unsigned char*>(base)[0] = 1;

CPU cố dịch địa chỉ ảo thành địa chỉ vật lý, nhưng PTE chưa có bản dịch hợp lệ sang trang vật lý. Page fault xảy ra ở đây.

Trình quản lý bộ nhớ nhận quyền điều khiển đánh giá đây là «lần truy cập đầu tới trang riêng đã Commit và ghi được», lấy một trang vật lý đã xóa không, gắn vào PTE và thêm vào Working Set. Rồi nó thực thi lại lệnh ghi đã thất bại.

Từ ứng dụng trông như một phép gán thường, nhưng bên trong điều khiển vào nhân giữa phép gán, trang vật lý được gán, và thực thi trở lại cùng lệnh.

4. VAD — sổ cái dải của không gian ảo

VAD viết tắt Virtual Address Descriptor, và Windows quản lý các dải địa chỉ đang dùng của tiến trình như cây VAD. Với lệnh !vad của WinDbg bạn có thể xem VPN đầu và cuối, Commit, thuộc tính bảo vệ, Private/Mapped, Control Area và hơn thế.3

Thông tin tiêu biểu VAD ghi gồm những mục sau.

  • Đầu và cuối dải địa chỉ
  • Loại như Private, Mapped hay Image
  • Trạng thái Reserve/Commit
  • Bảo vệ như đọc, ghi, thực thi và copy-on-write
  • Tương ứng với tệp hoặc section
  • Thuộc tính đặc biệt như trang canh

Lý do quản lý theo dải là hiệu quả. 256MiB là 65.536 trang ở 4KiB. Thay vì xây sẵn cấu trúc quản lý đầy đủ cho mọi trang, ít lãng phí hơn khi giữ «dải liên tục này là một chỗ dành» trong VAD và hiện thực hóa trang khi cần.

4.1. Tìm thấy VAD không bảo đảm phục hồi

«Nếu nằm trong VAD thì fault được giải; nếu không thì vi phạm truy cập» là lời giải thích nhập môn tiện, nhưng đơn giản hóa quá. Ngay cả khi tìm thấy VAD, truy cập thường không thể tiếp tục trong các trường hợp như sau.

  • Chỉ Reserve, và trang đích chưa Commit
  • PAGE_NOACCESS
  • Ghi vào trang chỉ đọc
  • Thực thi lệnh từ trang không thực thi được
  • Lần chạm đầu trang canh
  • Chạm ngoài dải hợp lệ của một section

Ngược lại, dù PTE không hợp lệ, nếu trạng thái phần mềm của VAD và PTE cho thấy truy cập hợp pháp, có thể giải bằng demand-zero, khôi phục Transition, page-in hoặc CoW. Chính xác hơn, câu trả lời là đánh giá cùng lúc VAD, PTE, thuộc tính bảo vệ và loại truy cập.

5. Bảng trang và TLB

Con trỏ ứng dụng giữ là địa chỉ ảo. Để CPU truy cập RAM, nó phải dịch số trang ảo thành số trang vật lý. Bảng dịch phân tầng đó là bảng trang, và mục lá là PTE (Page Table Entry).

PTE hợp lệ về khái niệm giữ PFN, bảo vệ đọc/ghi/thực thi, quyền chế độ người dùng, Accessed/Dirty và thông tin tương tự. Bố trí bit thực phụ thuộc CPU và phiên bản Windows.

Đi bảng trang mỗi lần sẽ quá chậm, nên CPU lưu bản dịch gần đây trong TLB (Translation Lookaside Buffer). Dịch địa chỉ diễn ra theo thứ tự này.

  1. Nếu TLB có bản dịch và truy cập khớp bảo vệ đó, dùng kết quả đó.
  2. Nếu TLB không có bản dịch, CPU đi bảng trang.
  3. Nếu có PTE hợp lệ và bảo vệ cũng khớp, đăng ký vào TLB và tiếp tục thực thi.
  4. Nếu không có bản dịch hợp lệ, hoặc có vi phạm bảo vệ, điều khiển đi tới điểm vào page fault. Kiểm tra bảo vệ cũng được thực hiện khi bản dịch đến từ TLB.

Như luồng này cho thấy, TLB miss và page fault là hai thứ khác nhau. Nếu vấn đề duy nhất là TLB không có bản dịch và PTE hợp lệ, chỉ xảy ra đi bảng trang. Ngược lại, dù TLB có bản dịch, vi phạm bảo vệ như ghi vào trang chỉ đọc hoặc thực thi lệnh trên trang không thực thi được vẫn đi tới điểm vào page fault. Đó là lý do ghi vào trang CoW có thể fault ngay cả khi bản dịch đã được lưu.

Luồng dịch địa chỉ và điểm vào page faultDù TLB có bản dịch, không khớp bảo vệ vẫn đi tới điểm vào page fault. Nếu TLB không có bản dịch thì đi bảng trang; PTE hợp lệ cũng khớp bảo vệ được đăng ký vào TLB và tiếp tục, còn bản dịch không hợp lệ hoặc vi phạm bảo vệ đi tới điểm vào page faultKhớpVi phạm bảo vệKhôngKhông hợp lệ hoặc vi phạm bảo vệTruy cập bộ nhớTLB có bản dịch không?Truy cập khớp bảo vệ không?Tiếp tục với bản dịch đóTới điểm vào page faultĐi bảng trangPTE hợp lệ và bảo vệ cũng khớp?Đăng ký TLB và tiếp tục(không fault)

Hình 3: TLB miss có thể giải bằng đi bảng trang. Điều khiển đi tới page fault khi bản dịch không hợp lệ hoặc có vi phạm bảo vệ, và vi phạm bảo vệ xảy ra cả khi TLB hit.

5.1. PTE không hợp lệ không chỉ là chỗ trống

Ngay cả PTE không hợp lệ cũng không rỗng. Từ trạng thái phần mềm của PTE không hợp lệ, Windows phân biệt các trường hợp như sau.

  • Trang demand-zero chưa từng được hiện thực
  • Trang Transition còn trong RAM
  • Trang dùng chung trỏ tới Prototype PTE
  • Trang riêng lưu trong tệp trang
  • Vi phạm bảo vệ hoặc vùng không hợp lệ

Việc của CPU chỉ là quyết định «đây không phải bản dịch hợp lệ thường» và giao cho nhân; trình quản lý bộ nhớ cung cấp ý nghĩa từ đó.

6. Page fault từ đầu đến cuối

Hãy lần theo lần ghi đầu vào trang riêng đã Commit qua sáu giai đoạn.

  1. CPU cố ghi.
    Nó kiểm tra TLB và bảng trang, nhưng PTE đích không có PFN hợp lệ.
  2. CPU nâng page fault.
    Nó chuyển địa chỉ ảo bị fault, loại đọc/ghi/thực thi, người dùng/nhân, và vấn đề là thiếu bản dịch hay vi phạm bảo vệ cho nhân.
  3. Trình quản lý bộ nhớ xem VAD và PTE.
    Nó quyết định trang đã Commit chưa, bảo vệ có khớp không, và cái nào trong demand-zero, Transition, dùng chung, page-in, CoW hay ngoại lệ áp dụng.
  4. Nếu là demand-zero, lấy trang vật lý đã xóa không.
    Trang vừa giao phải là không để dữ liệu tiến trình khác không bị rò.
  5. Thông tin quản lý PTE và PFN được cập nhật.
    PFN và bảo vệ được đặt trong PTE, trang vật lý thành Active, và được thêm vào Working Set của tiến trình.
  6. Lệnh thất bại được thực thi lại.
    Vì fault giải bình thường, không có ngoại lệ chế độ người dùng được giao, và ứng dụng tiếp tục phép gán như thường.

Sự kiện ETW page fault cũng ghi Transition, Demand Zero, Copy-on-Write, Guard Page, Hard Page Fault và Access Violation thành các loại riêng.4

Vậy page fault không phải từ có nghĩa «bất thường» từ đầu. Đó là điểm vào chung để nhờ hệ điều hành quyết khi CPU không dịch được trên đường thường.

Phân nhánh cách giải page faultTrình quản lý bộ nhớ đánh giá VAD, PTE, thuộc tính bảo vệ và loại truy cập, rồi chuyển tới demand-zero, nối lại trang còn trong RAM, hard fault từ backing store, copy-on-write, thông báo trang canh hoặc ngoại lệLần truy cập đầuCòn trong RAMCần đọc đĩaGhi CoWTrang canhKhông giải đượcPage fault xảy raĐánh giá VAD, PTE, bảo vệ, loạiDemand-zero(mềm)Nối lại từ Standby(mềm)Hard fault(I/O đĩa)Sao chép và đổi PTEGỡ canh và thông báoNgoại lệ(0xC0000005 v.v.)

Hình 4: Fault vào cùng một điểm vào tách thành sáu loại kết cục tùy đánh giá. Chi tiết trang canh ở mục 9.

7. Demand-zero — soft fault không đọc đĩa

Demand-zero là soft fault tiêu biểu xảy ra khi lần đầu chạm trang riêng đã Commit. Tài liệu Working Set của Microsoft cũng liệt «tiến trình tham chiếu lần đầu tới trang ảo đã cấp» làm ví dụ soft fault.5

Demand-zero có các đặc điểm sau.

  • Không cần đọc dữ liệu gốc từ đĩa
  • Nội dung ban đầu là không
  • Một trang vật lý sẵn có được gắn
  • Working Set và Page Fault Count tích lũy tăng
  • Chỉ xử lý này không tăng Memory\\Pages Input/sec

Đó là lý do đỉnh Page Faults/sec ngay sau khởi động tự nó không có nghĩa lưu trữ là nút thắt.

Đánh đổi của cấp phát lười cũng đáng sắp xếp. Nếu bạn Commit 256MiB và thực sự chỉ dùng 8MiB, để 248MiB còn lại ngoài RAM là hợp lý. Đổi lại, lần truy cập đầu mang chi phí xử lý fault. Với công việc nhạy trễ có thiết kế chạm từng trang trước khi bắt đầu để prefault, nhưng đó là đánh đổi tăng cư trú RAM từ trước.

8. Soft fault và hard fault

8.1. Soft fault

Soft fault là fault giải được mà không cần I/O đọc tới backing store. Các ví dụ tiêu biểu gồm những mục sau.

  • Demand-zero
  • Nối lại trang còn trên Standby/Transition
  • Nối trang dùng chung đang ở Working Set tiến trình khác
  • Nối trang đã prefetch
  • Copy-on-Write mà trang gốc còn cư trú

Vẫn có chi phí CPU cho chuyển nhân, khóa, cập nhật PTE/PFN, nhất quán TLB và tương tự, nhưng không chờ lưu trữ.5

8.2. Hard fault

Mặt khác, khi trang cần không ở đâu trong RAM và phải đọc từ backing store, đó là hard fault. Nguồn đọc không chỉ là tệp trang.

  • Trang riêng đã ghi ra tệp trang
  • Tệp ánh xạ bộ nhớ
  • Ảnh EXE hoặc DLL
  • Tệp dữ liệu mà bộ nhớ đệm tệp tham chiếu

Sự kiện ETW HardFault gồm FileObject, ReadOffset và ByteCount, nên bạn có thể lần nguồn đọc thực.6

Do đó Hard Fault = đọc pagefile.sys không đúng.

Khi cần đọc backing store, yêu cầu vào ngăn xếp I/O Windows. Luồng IRP và phát hành/hoàn tất được trình bày trong «The Depths of Windows I/O (Part 1)», và chỗ nối với bộ nhớ đệm tệp trong «The Depths of Windows I/O (Part 4)». Nếu trang ở RAM, trình quản lý bộ nhớ có thể tự trở về; nếu không, nó phát I/O và chờ luồng bị fault đến khi xong.

9. Fault không giải được trở thành ngoại lệ

Fault mà sau khi xem VAD và PTE không giải được như cấp phát hợp pháp, page-in hay CoW được giao cho chế độ người dùng như ngoại lệ.

Trường hợp tiêu biểu là STATUS_ACCESS_VIOLATION, mã ngoại lệ 0xC0000005. Nó xảy ra khi đọc, ghi hoặc thực thi địa chỉ không hợp lệ; tham số ngoại lệ thứ nhất chỉ loại truy cập, thứ hai chỉ địa chỉ vi phạm.7

Các mẫu điển hình gồm những mục sau.

  • Đọc NULL, địa chỉ đã giải phóng hoặc địa chỉ ngoài mảng
  • Ghi vào trang chỉ đọc
  • Thực thi lệnh từ trang mà DEP/NX đã làm không thực thi được
  • Chạm dải đã dành nhưng chưa Commit

PAGE_GUARD có nghĩa hơi khác. Đó là thông báo một lần về truy cập: nó nâng STATUS_GUARD_PAGE_VIOLATION và dùng cho việc như tăng stack.8

Cấp phát lười bình thường, page-in, CoW, thông báo canh và vi phạm truy cập cuối cùng, từ góc CPU, đều tụ tại cùng điểm vào page fault. Điều quyết kết cục là tổ hợp VAD, PTE, thuộc tính bảo vệ và loại truy cập.

10. Tự xem

Bạn có thể quan sát luồng đến đây trên máy mình. Chương trình C++ sau Reserve 256MiB, Commit, ghi một byte vào mỗi trang, rồi cuối cùng Release. Nó chờ Enter ở mỗi giai đoạn để bạn quan sát thay đổi trong VMMap và PerfMon.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <psapi.h>

#include <cstdio>
#include <cstdlib>

#pragma comment(lib, "Psapi.lib")

constexpr SIZE_T kSize = 256ull * 1024 * 1024;

void PrintMemory(const char* stage)
{
    PROCESS_MEMORY_COUNTERS_EX c{};
    c.cb = sizeof(c);
    if (!GetProcessMemoryInfo(
            GetCurrentProcess(),
            reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&c),
            sizeof(c))) {
        std::printf("GetProcessMemoryInfo failed: %lu\n", GetLastError());
        return;
    }

    std::printf(
        "%-10s WS=%zu MiB  Private=%zu MiB  Faults=%lu\n",
        stage,
        c.WorkingSetSize / 1024 / 1024,
        c.PrivateUsage / 1024 / 1024,
        c.PageFaultCount);
}

void Pause(const char* message)
{
    PrintMemory(message);
    std::puts("Press Enter...");
    (void)std::getchar();
}

int main()
{
    SYSTEM_INFO si{};
    GetSystemInfo(&si);
    std::printf("PID=%lu, page=%lu bytes\n",
                GetCurrentProcessId(), si.dwPageSize);

    void* base = VirtualAlloc(nullptr, kSize, MEM_RESERVE, PAGE_NOACCESS);
    if (!base) {
        std::fprintf(stderr, "Reserve failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("reserved");

    if (!VirtualAlloc(base, kSize, MEM_COMMIT, PAGE_READWRITE)) {
        std::fprintf(stderr, "Commit failed: %lu\n", GetLastError());
        VirtualFree(base, 0, MEM_RELEASE);
        return EXIT_FAILURE;
    }
    Pause("committed");

    auto* bytes = static_cast<volatile unsigned char*>(base);
    for (SIZE_T offset = 0; offset < kSize; offset += si.dwPageSize) {
        bytes[offset] = 1;
    }
    Pause("touched");

    if (!VirtualFree(base, 0, MEM_RELEASE)) {
        std::fprintf(stderr, "Release failed: %lu\n", GetLastError());
        return EXIT_FAILURE;
    }
    Pause("released");
}

Từ x64 Native Tools Command Prompt của Visual Studio, bạn có thể dựng bằng lệnh sau.

cl /std:c++20 /EHsc /W4 memory_fault_demo.cpp

10.1. Nhìn gì trong VMMap

VMMap là công cụ hiển thị bộ nhớ ảo đã dành, Commit, Working Set, Private và Shareable theo loại.9 Thay đổi kỳ vọng ở mỗi giai đoạn như sau.

Giai đoạn Thay đổi kỳ vọng
Reserve Address Space Size tăng, nhưng Commit/WS không tăng cùng lượng
Commit Private Commit tăng khoảng 256MiB
Touch Working Set và Private WS tăng rõ, Fault Count cũng tăng
Release Dải đích biến mất, Commit và WS giảm

Số thực tế thay đổi theo runtime, sản phẩm bảo mật, áp lực bộ nhớ và lúc bạn quan sát. Hãy nhìn số đi hướng nào giữa các giai đoạn, không phải có ra đúng 256MiB hay không.

10.2. Tách mềm và cứng trong PerfMon

Trong PerfMon, đặt các bộ đếm sau trên cùng trục thời gian.

  • Process(<target>)\\Page Faults/sec
  • Memory\\Pages Input/sec
  • Memory\\Page Reads/sec
  • Memory\\Available MBytes
  • Process(<target>)\\Working Set - Private
  • Process(<target>)\\Private Bytes

Process\\Page Faults/sec gồm cả soft fault và hard fault. Memory\\Pages Input/sec, ngược lại, là số trang đọc từ đĩa để giải hard fault.10

Ở giai đoạn Touch của chương trình này, Page Faults/sec nên nhảy trong khi Pages Input/sec không nên tăng nhiều. Các trang mới Commit được hiện thực bằng demand-zero, nên không cần đọc dữ liệu gốc từ đĩa.

Khi vài tiến trình chia cùng tên, số PerfMon như process#1 có thể đổi qua lần khởi động lại. Đối chiếu với bộ đếm hiện PID, hoặc nhận dạng theo PID bằng Process V2 hoặc ETW/WPA.

11. Ba cách đọc sai cần tránh trong thực tế

11.1. «Commit tăng nên đây là rò RAM»

Commit là lượng nội dung được hứa giữ; trang chưa chạm có thể không cư trú trong RAM. Để đánh giá rò, nhìn chuỗi thời gian Private Bytes, phân tách cấp phát, và số có trở về đường cơ sở sau khi xử lý xong không.

11.2. «Page Faults/sec cao nên đĩa chậm»

Soft fault không có I/O đĩa. Tách Page Faults/sec, Pages Input/sec và chờ lưu trữ, và nếu cần lần tệp nguồn cùng ngăn xếp bằng sự kiện ETW HardFault.

11.3. «Làm trống Working Set sẽ sửa rò»

Gỡ trang khỏi Working Set không giải phóng Commit hay sở hữu. Trang đi sang Standby hoặc Modified rồi fault trở lại sau. Sửa rò cần bộ cấp phát thực hiện VirtualFree, giải phóng heap, hủy đối tượng và tương tự.

Trang vật lý bị gỡ đi đâu là điều ta lần theo ở phần 2.

12. Tóm tắt

  • MEM_RESERVE dành dải địa chỉ ảo nhưng không gán vùng vật lý trong RAM hay tệp trang.1
  • MEM_COMMIT tiêu hao Commit và bảo đảm nội dung có thể được giữ trong tương lai, nhưng trang vật lý thường không được gán cho đến lần truy cập đầu.12
  • VAD là sổ cái dải, PTE sổ cái trang ảo, cơ sở PFN sổ cái trang vật lý.
  • TLB miss không phải page fault. Nếu PTE hợp lệ, chỉ đi bảng trang là giải được.
  • Demand-zero, khôi phục Transition và nối trang dùng chung là soft fault giải được không cần I/O đĩa.5
  • Nếu cần đọc từ tệp trang, DLL, EXE hoặc tệp ánh xạ, đó là hard fault.6
  • Nếu kiểm tra VAD, PTE và thuộc tính bảo vệ không giải được fault, bạn nhận ngoại lệ như 0xC0000005.7
  • Để đánh giá hiệu năng, đừng chỉ nhìn Page Faults/sec; nhìn Pages Input/sec, Available, Working Set, Private Bytes và chờ lưu trữ trên cùng trục thời gian.

Tiếp theo phần 2, «Đời một trang vật lý: năm danh sách và sự thật về tệp trang».

Sau khi lời hứa Commit đã thành trang vật lý, ta lần theo trang đó đi đâu khi rời Working Set, từ cơ sở PFN và các danh sách trang.

Bài viết liên quan

Lĩnh vực tư vấn liên quan

KomuraSoft LLC xử lý điều tra mức dùng bộ nhớ ứng dụng Windows, vi phạm truy cập, trễ khởi động, phân trang và khiếm khuyết mã gốc.

Liên kết tham khảo

  1. Microsoft Learn, VirtualAlloc function. Về MEM_RESERVE dành dải địa chỉ ảo mà không gán lưu trữ vật lý; MEM_COMMIT ghi nhận commit charge đối với bộ nhớ và tệp trang hệ thống; nội dung ban đầu của trang đã Commit là không; và trang vật lý thực không được gán cho đến khi được truy cập.  2 3 4 5 6

  2. Microsoft Learn, PERFORMANCE_INFORMATION structure. Về CommitTotal là số trang Commit hiện tại của hệ thống, và CommitLimit là cận trên có thể Commit mà không mở rộng tệp trang.  2

  3. Microsoft Learn, !vad (WinDbg). Về !vad hiển thị cây VAD và cho phép xem VPN đầu và cuối, Commit, Mapped/Private, thuộc tính bảo vệ, Control Area và hơn thế. 

  4. Microsoft Learn, PageFault_TypeGroup1 class. Về ETW phân biệt và ghi Transition Fault, Demand Zero Fault, Copy-on-Write, Guard Page Fault, Hard Page Fault và Access Violation. 

  5. Microsoft Learn, Working Set. Về soft fault giải được mà không truy cập backing store, và xảy ra từ Working Set tiến trình khác, Transition, demand-zero tham chiếu đầu và tương tự.  2 3

  6. Microsoft Learn, PageFault_HardFault class. Về sự kiện HardFault gồm FileObject, ReadOffset, ByteCount, VirtualAddress và ID luồng, nên có thể lần nguồn đọc.  2

  7. Microsoft Learn, Access Violation C0000005. Về 0xC0000005 xảy ra khi đọc, ghi hoặc thực thi địa chỉ bộ nhớ không hợp lệ, và tham số ngoại lệ chỉ loại truy cập cùng địa chỉ vi phạm.  2

  8. Microsoft Learn, Creating Guard Pages. Về PAGE_GUARD cung cấp thông báo một lần về truy cập trang và nâng STATUS_GUARD_PAGE_VIOLATION

  9. Microsoft Learn, VMMap - Sysinternals. Về VMMap tách bộ nhớ ảo đã Commit theo loại và hiển thị Working Set từng loại cùng bản đồ địa chỉ chi tiết. 

  10. Microsoft Learn, Performance Analysis of Logs (PAL) Tool. Về Memory\\Pages Input/sec là số trang đọc từ đĩa để giải hard page fault. 

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.

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.

Bài viết liên quan trực tiếp đến các dịch vụ sau.

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.

Truyền MEM_COMMIT cho VirtualAlloc có cấp RAM ngay lúc đó không?
Trong bộ nhớ riêng thông thường, Commit tiêu hao dư địa commit của hệ thống, nhưng trang vật lý tương ứng chưa được gán cho đến lần truy cập đầu. Trang lần đầu chạm bằng ghi nhận trang vật lý trong lúc xử lý demand-zero fault.
Page fault có nghĩa là có sự cố hoặc vấn đề hiệu năng không?
Không. Soft fault không có I/O đĩa — như demand-zero hoặc trả trang từ Standby — là vận hành bình thường. Để đánh giá hiệu năng, đừng chỉ nhìn Page Faults/sec mà còn Pages Input/sec, chờ lưu trữ và Available MBytes.
TLB miss và page fault có phải cùng một thứ không?
Chúng khác nhau. Dù TLB không có bản dịch, nếu PTE của bảng trang hợp lệ CPU chỉ đi bảng và đăng ký lại bản dịch. Nó đi tới điểm vào page fault khi PTE không hợp lệ hoặc có vi phạm bảo vệ.
Nếu dải địa chỉ nằm trong VAD thì không thể bị vi phạm truy cập?
Không nhất thiết. Ngoài việc có VAD, trình quản lý bộ nhớ còn đánh giá Reserve so với Commit, bảo vệ đọc/ghi/thực thi, trang canh, trạng thái PTE và hơn thế. Nếu không giải được fault, bạn nhận ngoại lệ như 0xC0000005.
Page Faults/sec cao có nghĩa hệ thống thiếu RAM không?
Chỉ thế thì không biết được. Page Faults/sec cũng gồm rất nhiều soft fault. Cần đối chiếu trên cùng trục thời gian với Memory\Pages Input/sec, Memory\Page Reads/sec, Available MBytes và thời gian chờ đĩa.

Hồ sơ tác giả

Trang giới thiệu tác giả bài viết.

Go Komura

Đại diện của KomuraSoft LLC

Chuyên về phát triển phần mềm Windows, tư vấn kỹ thuật và điều tra lỗi, đặc biệt trong các dự án có hệ thống hiện hữu và lỗi khó tái hiện.

Liên kết công khai

Quay lại blog